を使用した結果、とは、いくつかのコードを試してみました。この結果には理由がありますか?未定義のプロトタイプ[ジャバスクリプト]だから私はJavaScriptを使用してプロトタイプを学んでいる
私はいくつかのテストを行いました。私は、プロトタイプオブジェクトを再割り当てすると、以前に作成されたEmployeeクラスのインスタンスは、新しく割り当てられたプロトタイプ内にあるプロパティにアクセスできなくなると結論づけました。これは正確ですか?
を使用した結果、とは、いくつかのコードを試してみました。この結果には理由がありますか?未定義のプロトタイプ[ジャバスクリプト]だから私はJavaScriptを使用してプロトタイプを学んでいる
私はいくつかのテストを行いました。私は、プロトタイプオブジェクトを再割り当てすると、以前に作成されたEmployeeクラスのインスタンスは、新しく割り当てられたプロトタイプ内にあるプロパティにアクセスできなくなると結論づけました。これは正確ですか?
まず第一に、あなたは前Employee
のインスタンスを作成しましたオブジェクトが新しいプロトタイプ値を継承しないように、プロトタイプを設定します。
次に、プロトタイプを設定した後に作成されたオブジェクトは、新しいプロトタイプオブジェクトを継承します。
最後に、オブジェクトはworking
プロパティではなくisWorking
プロパティを持ちます。だからあなたの例をやり直す
:
function Employee(name) { this.name= name; };
var m1 = new Employee("Bob");
var working= { isWorking: true };
Employee.prototype = working;
var m2 = new Employee("Sam");
alert(m1.isWorking); // undefined
alert(m2.isWorking); // true
プロトタイプを変更しても、すでに作成されたオブジェクトには影響しません。そのオブジェクトに基づいて作成されたオブジェクトにのみ影響します。
プロトタイプを変更するために使用できるプロパティ__proto__
がありますが、その実装は必須ではありません。 ES6では、setPrototypeOf
というプロトタイプの変更方法が定義されていますが、ES6でしかサポートされていないため、サポートが異なる場合があります。
簡単に修正するには、正しく割り当てます。
function Employee(name) {
this.name = name;
}
var m = new Employee("Bob");
var working = {
isWorking: true
};
Employee.prototype.working = working;
alert(m.working.isWorking);
複数の従業員のためのより良い修正は、クラスを作る、そののインスタンスを作成することです。ここでそれで遊ぶ:http://jsfiddle.net/MarkSchultheiss/p6jyqbgv/1/
"use strict";
function makeClassStrict() {
var isInternal, instance;
var constructor = function(args) {
if (this instanceof constructor) {
if (typeof this.init == "function") {
this.init.apply(this, isInternal ? args : arguments);
}
} else {
isInternal = true;
instance = new constructor(arguments);
isInternal = false;
return instance;
}
};
return constructor;
}
var EmployeeClass = makeClassStrict();
EmployeeClass.prototype.init = function(employeeName, isWorking) {
var defaultName = 'notbob';
this.name = employeeName ? employeeName : defaultName;
this.working = !!isWorking;
};
// call this to get the name property
EmployeeClass.prototype.getName = function() {
return this.name
};
//note no "new" needed due to the makeClassStrict that does that
var m = EmployeeClass("Bob");
alert(m.working +":"+ m.name);
m.working = true;
alert(m.working +":"+ m.name);
var notbob = EmployeeClass("Charlie",false);
alert(notbob.working +":"+ notbob.name);
alert(notbob.getName()+ m.getName());
あなたは全体のprototypeプロパティをオーバーライドして、既存のインスタンスが動作するように期待することはできません。 JavaScriptはそのようには機能しません。しかし、プロトタイプオブジェクトをループして、すでに設定されているものをすべて解除してから、新しいオブジェクトをループして別のものに設定することができます。
function Employee(name) { this.name= name; }
var m = new Employee("Bob");
var working= { isWorking: true };
for(var j in Employee.prototype){delete Employee.prototype[j];}//unset all properties, the same as setting to {}
for(j in working){Employee.prototype[j]=working[j];}//set the properties
alert(m.isWorking);
プロトタイプの明示的に宣言された属性は、暗黙のうちに 'delete'キーワードを使用して削除することはできません。 –
@Æðelstan自分自身を参照してください:http://jsfiddle.net/L2yvjtow/ – Ultimater
それは、良い点が動作します! –
インスタンスを作成すると、その時点でコンストラクタのプロトタイプへの参照が取得されます。後でプロトタイプを置き換えた場合、既存のインスタンスはそれを反映しません。インスタンスを作成したら、プロトタイプを置き換えるのではなく、拡張することが一般的に予想されます。 –
プロトタイプオブジェクトへのインスタンスの参照は、構築時に設定されます(つまり、 'new'を含む行)。 'Foo.prototype'プロパティオブジェクト全体を変更しても、後でこの参照は変更されません。しかし、 'Foo.prototype'オブジェクトへの変更は(同じオブジェクトであるため)見ることができます。あなたが代わりに 'Employee.prototype.isWorking = true;'を実行した場合、あなたが期待しているものが表示されます –
さらに読むために、これはprototypal継承の本当に良い実行です:http://markdalgleish.com/2012/10/a -touch-of-class-inheritance-in-javascript/ – br3nt