【问题标题】:reference and primitive prototype values [duplicate]参考和原始原型值
【发布时间】:2012-05-17 05:17:40
【问题描述】:

我不明白为什么数组在两个实例之间共享而原始类型不是。有人可以解释一下吗?

MyObject = function() {};
MyObject.prototype = {anArray : [],aString : ''};
var c1 = new MyObject();
c1.aString = 'a';
c1.anArray.push('a');
var c2 = new MyObject();
console.log(c2.aString);
console.log(c2.anArray);

【问题讨论】:

  • 原始类型 在两个实例之间共享,但是您已经覆盖了 c1 对象自己的值。

标签: javascript javascript-objects


【解决方案1】:

字符串是不可变的,数组是可变的。您正在替换字符串,但修改数组。

如果您覆盖数组而不是修改它,您将在数组和字符串之间获得相同的行为。

MyObject = function() {};
MyObject.prototype = {anArray : [],aString : ''};

var c1 = new MyObject();
c1.aString = 'a';
c1.anArray = []
c1.anArray.push('a');

var c2 = new MyObject();
console.log(c2.aString); // ''
console.log(c2.anArray); // []

因此,如果您计划允许所有实例观察其更改,那么将对象或数组放在 prototype 上才有意义。否则,直接放在实例上即可。

MyObject = function() {
    this.anArray = [];
};
MyObject.prototype = {aString : ''};

【讨论】:

  • 感谢您的回复。那么,拥有可变实例变量的推荐方法是什么?
  • @bradmiley: 让数组远离原型,并直接将其分配给构造函数中的新对象。
【解决方案2】:

当你分配时

c1.aString = 'a'

没有分配给原型中的aString 字段。直接在c1 对象中创建了一个名为aString 的新字段,并在原型中隐藏了aString 字段。

同时,当你打电话时

c1.anArray.push('a');

c1 中没有 anArray 字段,因此您在原型中引用了 anArray。您可以通过这样做来测试它

c1.anArray = new Array();

并注意在c1 中创建了一个新属性anArray,不会干扰原型中的anArray。在这种情况下,

console.log(c1.anArray);
console.log(c2.anArray);

会有不同的结果,因为c2 仍然会引用原型中的anArray

如果在对象和原型中(甚至在原型链中)都存在同名的字段,并且您请求该字段的值,则解释器首先直接查看对象,仅然后沿着原型链向上,直到在某处找到该字段。

然而,如果你给一个字段赋值,它总是直接在对象中完成,而不是在它的原型中。

【讨论】:

    猜你喜欢
    • 2012-10-27
    • 1970-01-01
    • 2020-02-19
    • 2016-03-31
    • 2015-09-06
    • 2011-09-30
    • 1970-01-01
    • 2021-10-27
    • 1970-01-01
    相关资源
    最近更新 更多