Javascript 使用 Object.create 和属性指针未从原型中取消引用

Javascript use of Object.create and properties pointers not being dereferenced from prototype

谁能解释一下当我 o1.set('bar'); 时发生了什么?我想知道为什么此时也设置了 o2.name,而当我设置 o2.set('fox'); 时却没有发生同样的情况,我的意思是,o1.name 仍然是 bar

为什么 o1.name 和 o2.name 指向同一个对象,即使我更改了旧值 (foo) 但当我更改 o2.name?

var Person = {
 name: "foo",
 get: function get() {
  return this.name;
 },
 set: function set(sur) {
  this.name = sur;
 }
},
o1 = Person,
o2 = Object.create(o1);

// true "foo" "foo"
console.log(o1.name === o2.name, o1.get(), o2.get()); 

o1.set('bar');

// true "bar" "bar"
console.log(o1.name === o2.name, o1.get(), o2.get());

o2.set('fox');

// false "bar" "fox"
console.log(o1.name === o2.name, o1.get(), o2.get());

下面可以看到另一个行为。这里的不同之处在于,我什至为 o1 对象扩展了 Person 原型。

 var Person = {
  name: "foo",
  get: function get() {
   return this.name;
  },
  set: function set(sur) {
   this.name = sur;
  }
 },
 o1 = Object.create(Person),
 o2 = Object.create(Person);

 // true "foo" "foo"
 console.log(o1.name === o2.name, o1.get(), o2.get()); 

 o1.set('bar');

 // false "bar" "foo"
 console.log(o1.name === o2.name, o1.get(), o2.get());

 o2.set('fox');

 // false "bar" "fox"
 console.log(o1.name === o2.name, o1.get(), o2.get());

对象 o2 从其原型链继承 "name" 属性。但是,一旦 属性 被设置,对象本身就会受到影响。

换句话说,在设置对象 属性 时不参考原型链。 属性 更新(或添加)总是直接在目标对象上。仅在检查 属性 个值时才参考原型链。

This 在调用o2.set("fox"); set() 函数时本身就找到了原型。但是,该调用中 this 的值是 o2,而不是 o1,因此对 this.name 的赋值会直接影响 o2

答案可以在 Eric Elliot 的好书“Programming JavaScript Applications”中找到,我认为这可以在这里找到问题 Delegate Prototypes

埃里克说:

"在 JavaScript 中,对象具有对委托原型的内部引用。当查询对象的 属性 或方法时,JavaScript 引擎首先检查对象。如果该对象上不存在键,它将检查委托原型,依此类推原型链。原型链通常在对象原型处结束。"

并完成解释:

"原型上的属性就像默认值一样。当您在实例上设置它们时,实例值仅会覆盖该实例的值。"

换句话说,我知道调用 o1.get() 时我正在更改原型,而 o2 对象正在扩展它。但是,当我调用 o2.get() 时,我不再更改原型而是 o2 实例。这就是为什么在那之后 o1.name 上的任何更改现在都与 o2.name 分离。