Tibos の方法で Object.create を使用すると、渡されたオブジェクトのすべてのメンバーがprototype
、返されたオブジェクトの に配置されるように見えます。
// in firefox firebug running
// an empty page
var Definition = {
name : 'Test1'
};
//doesn't matter where it's defined
Definition.greet=function() {
console.log(this);//<-what is this in Chrome?
};
Definition.arr=[];
// instance of Test1
var test1 = Object.create(Definition);
var test2 = Object.create(Definition);
console.log(test1.greet===test2.greet);//true
delete test2.greet
delete test2.greet
delete test2.greet
delete test2.greet//can't delete it
test2.greet();
console.log(test1.greet===test2.greet);//true
console.log(test1.arr===test2.arr);//true
test1.arr.push(1);
console.log(test2.arr);//=[1]
var things=[];
for(thing in test1){
things.push(thing);
}
console.log("all things in test1:",things);
things=[];
for(thing in test1){
if(test1.hasOwnProperty(thing)){
things.push(thing);
}
}
console.log("instance things in test1:",things);//nothing, no instance variables
[アップデート]
上記のコードからわかるように、Object.create は、プロトタイプの最初のパラメーターのすべてのメンバーと、インスタンス メンバーとしての 2 番目のパラメーターを持つオブジェクトを返します。(答えはコメントに mccainz から長い間ありました) 追加の利点 (何年も更新されていない IE8 とブラウザーを無視します) は、インスタンス メンバーで列挙可能、書き込み可能、および構成可能を指定でき、ゲッターとセッターを作成できることです。割り当てのように機能します (instance.someprop=22 は実際には instance.someprop(22) になる可能性があります)。
インスタンス固有のメンバーを指定するには、いくつかのパターンを使用できます。これらのパターンを使用すると、コードは new キーワードを使用する場合と同じくらい「醜い」か、さらに悪いように見えますが、これは個人的な好みであり、ゲッターとセッターを作成したり、追加の制御 (列挙可能、書き込み可能および構成可能)。
1 つのパターンは、init 関数を使用することです。
var userB = {
init: function(nameParam) {
this.id = MY_GLOBAL.nextId();
this.name = nameParam;
},
sayHello: function() {
console.log('Hello '+ this.name);
}
};
var bob = Object.create(userB).init("Bob");
追加の制御を利用するより複雑なものは次のとおりです。
var Person={
talk:function(){console.log("I'm "+this.name);}
//,other prototype stuff related to Person
};
var userCreator={
processInstanceMembers:function(o,initObj){
this.createName(o,initObj.name);
Object.defineProperty(o,"_name",{writable:true});
o.name=initObj.name;
},
get:function(initObj,inheritFrom){
var ret=Object.create(inheritFrom||Person);
this.processInstanceMembers(ret,initObj);
return ret;
},
createName:function(o){//minimalise closure scope
Object.defineProperty(o,"name",{
get:function(){
return this._name;
},
set:function(val){
if(val.replace(/\s*/gm,"")===""){
throw new Error("Name can't be empty, or only whitespaces");
}
this._name=val;
},
enumerable : true
});
}
};
//when creating an instance you can choose what to inherit from
//leave it out to inherit from Person
var u=userCreator.get({name:"Ben"});
u.talk();
u.name="Benji";
u.talk();
u.name=" ";//error, name can't be empty
Child の継承を設定するために Parent の新しいインスタンスを作成する必要はありません。これまたはヘルパー関数に Object.create を使用できます。
var Child =function(){
//get Parent's INSTANCE members defined in the
//parent function body with this.parentInstance=...
Parent.apply(this,arguments);
}
Child.prototype=Object.create(Parent.prototype);
Child.prototype.constructor=Child;
Child.prototype.otherFn=function(){};
これは興味深いと思うかもしれません。ヘルパー関数があるため、必要がなければ Object.create を使用する必要はありません。