关于原型对象及其在Javascript继承中的作用

时间:2014-08-22 15:36:08

标签: javascript prototypal-inheritance prototype-programming

我刚刚开始搞乱Javascript继承,并且不能让我围绕这个:#/ p>

如果我运行此代码:

function Foo(y) {
    this.y = y;
}

Foo.prototype.x = 1;

var Bar1 = new Foo(2);
var Bar2 = new Foo(3);

我希望在内存中有以下“结构”: enter image description here 我在图形中搞砸了,Bar2的属性“y”显然值为“3”

幸运的是,我可以通过运行此代码来确认:

console.log("Prototype - x: ", Foo.prototype.x, " y: ", Foo.prototype.y);
console.log("Bar1 - x: ", Bar1.x, " y: ", Bar1.y);
console.log("Bar2 - x: ", Bar2.x, " y: ", Bar2.y);

打印:

Prototype - x: 1 y: undefined
Bar1 - x: 1 y: 2
Bar2 - x: 1 y: 3

如果我错了,请纠正我,但是当我尝试访问Bar1和Bar2对象中的属性x时,正如那些对象不是localy有一个名为x的属性,我得到了来自原型链中下一个对象的属性;即他们在“_ proto _”属性中存储的引用。

现在是我迷路的时候,因为如果我在那段代码之后改变x的值,就像这样:

Bar1.x = 10;

我现在跑

console.log("Prototype - x: ", Foo.prototype.x, " y: ", Foo.prototype.y);
console.log("Bar1 - x: ", Bar1.x, " y: ", Bar1.y);
console.log("Bar2 - x: ", Bar2.x, " y: ", Bar2.y);

我得到的是

Prototype - x: 1 y: undefined
Bar1 - x: 10 y: 2
Bar2 - x: 1 y: 3

而不是我期望的:

Prototype - x: 10 y: undefined
Bar1 - x: 10 y: 2
Bar2 - x: 10 y: 3

那时我只能通过假设每个对象都创建了Foo.prototype对象的副本来解释,但是如果我运行这个

console.log(Object.is(Foo.prototype, Bar1.__proto__), Object.is(Bar1.__proto__, Bar2.__proto__));

我得到true true,因此Bar1,Bar2都访问同一个对象。

为什么Bar1会为x显示不同的值,如果它们都是从同一个对象获取它的话?

3 个答案:

答案 0 :(得分:3)

这一行:

Bar1.x = 10;

不会更改原型中x的值。相反,它会为x创建一个新属性(Bar1),并为其分配10的值。因此,Bar1不再从原型中继承x,因为它现在拥有自己的属性x

Bar2仍然存在,这就是它仍然与原型值匹配的原因。

答案 1 :(得分:2)

非常简单:

  

分配始终在对象本身上创建或更新属性。

赋值永远不会影响原型链,即使该属性存在于链的某个位置(*)。

只有读取属性遍历原型链,停在实际拥有该属性的对象上。

如果您对技术问题感兴趣,请查看PutValue definition in the specification


(*):但是,如果原型链中存在该属性,则可能会对分配产生影响。如果属性存在且只读(不可写),则赋值不会 创建一个新属性。例如:

> var obj = Object.create(Object.create({}, {x: {value: 10}}));
undefined
> obj.x
10
> obj.x = 100;
100
> obj.x
10

答案 2 :(得分:0)

关于Bar1Bar2如何获得x的值,你是对的。但是当你分配Bar1.x = 10时,它会崩溃。

尝试访问x时,它首先从对象本身开始,然后向下爬行。我们假设您尝试访问Bar1.z。查找看起来像这样:

  1. Bar1.z
  2. Bar1.prototype.z
  3. Bar1.__proto__.z,即Foo.prototype
  4. Object.prototype.z(因为所有对象都自然地继承自Object
  5. 找不到
  6. z,返回undefined
  7. 通过分配Bar1.x,您可以有效地隐藏Bar1.__proto__.x的值,因为它将首先出现在查找中。