2

最后,我在下面的代码中看到了一种关闭的味道。

function create(parent) {
var F = function() {};
 F.prototype = parent;
return new F();
}

var masterObject = {a: "masterObject value"}
var object1 = create(masterObject);
var object2 = create(masterObject);
var object3 = create(masterObject);
var object3.a = "overridden value";

object1.a; // "masterObject value"
object2.a; // "masterObject value"
object3.a; // "overridden value"

masterObject.a = "new masterObject value"//value is changed now

object1.a; // "new masterObject value"
object2.a; // "new masterObject value"
object3.a; // "overridden value"

object1.a ,abject2.a 的值永久更改。这是因为我更改了全局变量还是关闭的影响?因为我没有再次调用 Create() 函数,为什么值会自动更改?最后一个问题“当我对全局变量进行更改时,这是否会自动影响使用该变量的所有对象?”在我看来,要使该变量生效,我应该再次调用 Create() 函数不是吗?

4

3 回答 3

3

当您访问 时object3.a,JavaScript 首先查看对象的属性。如果对象没有名为 的属性a,则接下来检查对象的原型。

Settingobject3.a = "overridden value";给出object3了一个名为 的属性a。它不会影响原型的a属性。

由于object1并且object2没有名为 的属性a,但它们的原型有,因此当您修改masterObjecta属性时,所有具有原型的对象的值都会全局更改masterObject

即使您提供了object3一个名为 的属性a,但您仍然可以访问原型的a属性,该属性保持不变:

object3.__proto__.a; // "new masterObject value"

基本上,通过提供object3一个名为 的属性a,您将对象的新属性“放在”原型属性的“前面”。

于 2013-01-06T10:31:31.640 回答
0

当您直接更改对象的“a”属性时(就像您所做的那样var object3.a = "overridden value";(前面不应该有 a var),您更改了该实例自己的“a”属性。

所以,真正发生的是:

object3.a = "overridden value";在这里,您在 object3 上创建了一个新属性。它以前没有“a”属性。然而,它的原型确实如此,因此object3.a是合法的,并且会引用原型的“a”属性。

masterObject.a = "new masterObject value"在这里,您更改所有对象的原型create()(由 创建)。因此,如果您访问对象上的属性“a”,它现在将被更改,除了那些具有自己的“a”属性的对象(例如 object3)。

于 2013-01-06T10:34:47.540 回答
0

发生这种情况是因为继承在基于原型的语言(例如 javascript)中是如何工作的。当您调用 时create(masterObject),您将返回一个函数对象(您调用的F)的新实例,其原型设置为masterObject。这意味着 、 和 的原型字段object1指向object2object3一个对象masterObject

该声明:

object3.a  = "overriden value"

创建一个名为ain的字段object3并为其分配字符串"overriden value",这就是您检查时得到的结果object3.a。但是当您查看时object1.a,解释器注意到该a字段不存在,object1因此它遵循原型链接到其父级并检查该字段是否名为a. 在这种情况下,原型链接指向的masterObject有一个名为的字段,该字段a保存字符串"masterObject value",这就是您所看到的。如果masterObject没有被调用的字段a,解释器将一次又一次地跟踪原型链接,直到找到一个a字段或直到它到达一个带有空原型链接的对象,然后它将返回该值undefined

因此,通过更改masterObject.a,您可以更改检查时看到的内容,object1.a并且object2.a因为object1object2没有名为 的字段a,所以他们从父级“继承”它,masterObject

当您检查时不会发生这种情况,object3.a因为您创建了一个名为ain的字段object3来保存字符串"overridden value"

如果在代码末尾添加:

delete object3.a;

您现在会看到"new masterObject value"object3.a因为object3不再有一个名为 的字段a,所以它从其父级“继承”它,masterObject.

于 2013-01-06T10:49:48.517 回答