これoptions
は、(プロトタイプの) クラスのプロパティであり、オブジェクトではないためです。
これを 2 番目の例の最後に追加して確認します。
console.log( p.options == p2.options ); // true
説明:
抽象化レイヤーを使用するときは、抽象化のリークに悩まされないように、基礎となる原則を覚えておくことが非常に重要です。
あなたの最初の例:
クラス定義を通常の Prototypal 継承で書き直してみましょう。
var Person = function (options) {
if (options) {
this.options = options;
}
};
Person.prototype.options = {value: 2};
var john = new Person();
john
の新しいインスタンスにPerson
なり、プロパティを持たなくoptions
なります:
john.hasOwnProperty('options'); // false
options
viaにアクセスしようとすると、プロトタイプ チェーンからjohn.options
が取得されます。{value: 2}
Person
ただし、コンストラクタに yourを指定して、この新しいオブジェクトを作成する場合options
:
var michael = new Person({value:5});
michael
プロパティがありoptions
ます:
michael.hasOwnProperty('options'); // true
2 つを比較する簡単なテストを次に示します。
john.options == Person.prototype.options // true
michael.options == Person.prototype.options // false
あなたの2番目の例:
次に、ネイティブの Prototypal 継承で記述された 2 番目の例を考えてみましょう。
var Person = function (options) {
if (options) {
for (var name in options) {
this.options[name] = options[name];
}
}
};
Person.prototype.options = {value: 2};
コンストラクターに渡すかどうかに関係なくoptions
、新しいオブジェクトには独自のoptions
プロパティがありません。あなたがしているのはoptions
、プロトタイプの を拡張することだけです:
var john = new Person();
john.options // {value:2}
john.hasOwnProperty('options'); // false
john.options == Person.prototype.options // true
var michael = new Person({value:5});
michael.options // {value:5}
michael.hasOwnProperty('options'); // false
michael.options == Person.prototype.options // true
john.options // {value:5}
// Why? Because they share the same `options` property from the prototype
john.options == michael.options // true
次に、新しいオブジェクトを に割り当てても、プロトタイプjohn
の には影響しません。options
john.options = {value:10};
john.options // {value:10}
john.options == Person.prototype.options // false
michael.options // {value:5}
michael.options == john.options // false
michael.options == Person.prototype.options // true
解決:
2 番目の例で必要な機能を取得するには、次の手順に従う必要があります。
- コンストラクター (メソッド)内から新しい
options
プロパティを作成します。init
- からすべてのプロパティをコピーします
Person.prototype.options
。
- 最後に、
options
引数からすべてのプロパティをコピーします。
これを行う方法は次のとおりです。
var Person = Class.extend({
options: {value: 2},
init: function(options) {
if (options) {
var name, prototypeOptions = Person.prototype.options;
this.options = {};
for (name in prototypeOptions) {
this.options[name] = prototypeOptions[name];
}
for (name in options) {
this.options[name] = options[name];
}
}
}
});
jQueryまたはunderscoreを使用している場合は、それらのextend
メソッドを使用できます。これにより、このすべてが簡単になります。
var Person = Class.extend({
options: {value: 2},
init: function(options) {
if (options) {
this.options = $.extend({}, Person.prototype.options, options);
}
}
});
より簡単な解決策:
必要に応じて、options
そもそも がプロトタイプである必要さえない場合もあります。init
コンストラクター (メソッド) でオブジェクトに追加するだけで完了です。
var Person = Class.extend({
init: function(options) {
this.options = {value: 2};
if (options) {
for (var name in options) {
this.options[name] = options[name];
}
}
}
});
繰り返しますが、jQuery またはアンダースコアを使用している場合、これはさらに簡単になります。
var Person = Class.extend({
init: function(options) {
this.options = _.extend({value: 2}, options);
}
});