使用Object.create

时间:2019-06-06 02:02:33

标签: javascript

众所周知,我们可以使用let obj1 = Object.create(obj)使obj1的原型指向obj。但是我发现的问题是,为什么两者之间的变化不是双向的?如代码所示。

var obj = { val: 1 };
var obj1 = Object.create(obj);

obj.val = 2;
console.log(obj.val);  // 2
console.log(obj1.val);  // 2

obj1.val = 3;
console.log(obj.val);  // 2
console.log(obj1.val);  // 3

为什么要更改obj的属性值,而obj1也会更改。但是我更改了obj1的属性值,但不会更改为obj吗?

为什么会有这样的区别?我听不懂你知道吗?你能告诉我原因吗?谢谢!

2 个答案:

答案 0 :(得分:1)

当您尝试访问对象的属性时,javascript首先检查对象是否拥有属性。如果找到它,那就太好了,它将解决该值。如果没有,它将原型链传递到父级并在此处进行检查。它会继续沿着原型链前进,直到找到它或到达链的末端为止,在这种情况下,该值是不确定的。

因此,当您访问obj1.val时,它将首先检查obj1.val。在第一种情况下,它找不到它,因此它检查obj.val并返回在那里找到的2。在您的第二种情况下,它发现它是自己的3属性,并且不检查obj.val。

相反,当您访问obj.val时,它将检查obj.val。在这两种情况下,它都找到它,并且它等于2。即使它未能找到自己的属性,它也不会检查obj1,因为obj1不在其原型链中。它将只检查根Object.prototype(这是定义.toString之类的对象的基本属性的位置)。

答案 1 :(得分:0)

这个简单的示例说明了创建具有完全相同结果的原型的不同方法。这说明了继承链的工作方式以及“阴影”的结果。

const GrandChild = {};
const Child = {};
const Parent = {};
const GrandParent = {
  name: "grandparent"
};

GrandChild.__proto__ = Child;
Child.__proto__ = Parent;
Parent.__proto__ = GrandParent;
GrandChild.__proto__ = Child;

console.log(GrandChild.name, Child.name, Parent.name, GrandParent.name);

Child.name = "Child";

console.log(GrandChild.name, Child.name, Parent.name, GrandParent.name);