プロトタイプを使用するという考え方は、オブジェクトのプロパティにアクセスしようとすると、インタプリタは最初に指定されたオブジェクトのそのプロパティを見つけようとするというものです。
指定されたオブジェクトでプロパティが見つからない場合、インタープリターは、プロトタイプチェーンがで終わるまで、オブジェクトのプロトタイプなどでプロパティを見つけようとしますnull
。
プロパティが見つからない場合、インタプリタはを返しますundefined
。それ以外の場合は、プロパティ値を返します。
あなたの場合、プロパティsex
にアクセスしているとき、それはオブジェクトにはありませんが、オブジェクトのプロトタイプにはあります。したがって、を返しますmale
。
次に、それに新しい値を割り当てると、sex
JavaScriptは動的言語であるため、オブジェクトのプロトタイプのプロパティを変更する代わりに、指定されたオブジェクトに新しいプロパティを作成します。
新しい値が古い値をシャドウするため、これは問題ありません。これがプロトタイプの継承の仕組みです。
指定されたオブジェクトではなくプロトタイプのプロパティを明示的に更新する場合は、次のようにオブジェクトにプロパティを作成することをお勧めします。
function defineProperty(object, name, value) {
Object.defineProperty(object, name, {
value: value,
writable: true,
enumerable: true
});
}
function extendObject(object) {
var extendedObject = Object.create(object);
Object.keys(object).forEach(function (key) {
Object.defineProperty(extendedObject, key, {
set: function (value) {
object[key] = value;
},
enumerable: true
});
});
return extendedObject;
}
var man = Object.create(null);
defineProperty(man, "sex", "male");
var yehuda = extendObject(man);
defineProperty(yehuda, "firstName", "Yehuda");
defineProperty(yehuda, "lastName", "Katz");
これで問題が解決するはずです。プロトタイプの継承について詳しく知るには、この回答を読んでください。
編集:プロトタイプの値を変更しようとしないことをお勧めします。これは、多くのオブジェクトが同じプロトタイプを持っている可能性があるためです。プロトタイプの値を変更すると、それに依存するすべてのオブジェクトに変更が反映されます。それがあなたが達成したいことでない限り、私はあなたがプロトタイプチェーンのシャドウイングプロパティでやることを提案します。
注:オブジェクトのプロパティは削除できます。削除したプロパティが別のプロパティをシャドウイングしていた場合、次に同じプロパティ名にアクセスしたときにシャドウイングされたプロパティが使用されます。