JavaScript对象是单向链接还是双向链接?

时间:2013-11-14 07:08:19

标签: javascript inheritance

我正在尝试Douglas Crokford视频中的这个例子,据我所知,更改新对象不应该改变旧对象。

   var oldObject = {
        firstMethod:function(){
            console.log("This is first method");
        },
        secondMethod:function(){
            console.log("This is second method");
        }
    }

    var newObject = Object(oldObject);

    newObject.thirdMethod=function(){
        console.log("thirdMethod");
    }

    newObject.firstMethod=function(){
        console.log("I am not first method");
    }

    newObject.firstMethod();
    oldObject.firstMethod();

输出:

I am not first method
I am not first method

但我期待,

I am not first method
This is first method

请告诉我错误的地方。

4 个答案:

答案 0 :(得分:1)

如果你调用the Object constructor as a function,它会执行类型转换(在这种情况下没有任何内容,因为参数已经是一个对象)。 (如果你去call it as a constructor并传递一个对象,就像你那样,那么它只返回那个对象。)

newObject不是新对象,而是相同的对象。因此,对newObject的任何修改也都是对oldObject的修改。

可能你想要:

var newObject = {};
newObject.prototype = oldObject;

而不是Object()来电。

答案 1 :(得分:1)

TL; DR:这是(很可能)你的代码中的一个拼写错误:它应该是这样编写的:

var newObject = Object.create(oldObject);

现在进行解释。这条线......

var newObject = Object(oldObject);

...不会创建新对象:而是newObject变量变为存储对同一对象oldObject所引用的引用。以下是standard对此的说法:

  

15.2.1.1:当没有参数或一个参数值调用Object函数时,采取以下步骤:

     
      
  1. 如果value为null,未定义或未提供,则创建并返回一个新的Object对象,就像使用相同的参数调用标准的内置Object构造函数一样
  2.   
  3. 返回ToObject(值)。
  4.         

    9.9:抽象操作ToObject将其参数转换为值   根据表14输入Object:[...]

         

    对象:结果是输入参数(无转换)。


您可能想要做的是使用oldObject作为新原型的原型。当你已经拥有一个对象时,最“直接”的方式就是使用__proto__属性:

var newObject = {
  firstMethod: function() { console.log("I am not the firstMethod"); },
  thirdMethod: function() { console.log("thirdMethod"); } 
};
newObject.__proto__ = oldObject;

这些功能现在无处不在(除了IE10-,基本上所有现代浏览器support)。它不是ES5标准的一部分,但它可能属于ES6。

但我猜Crockford实际上就是这样说的:

var newObject = Object.create(oldObject);

...因此,再次引用standard,'创建一个带有指定原型的新对象'。

答案 2 :(得分:0)

是的,当您尝试在javascript中复制对象时,它只是将其作为对原始对象的引用传递,因此对新对象的任何更改都会影响原始对象。如果您使用的是jQuery,请执行以下操作:

var newObject = $.extend({},oldObject);

那应该可以解决你的问题。请查看此更深入的答案:How do I correctly clone a JavaScript object?

修改

另外,从上面的线程中得到一个非jQuery解决方案:

Object.prototype.clone = function() {
  if(this.cloneNode) return this.cloneNode(true);
  var copy = this instanceof Array ? [] : {};
  for(var attr in this) {
    if(typeof this[attr] == "function" || this[attr]==null || !this[attr].clone)
      copy[attr] = this[attr];
    else if(this[attr]==this) copy[attr] = copy;
    else copy[attr] = this[attr].clone();
  }
  return copy;
}

答案 3 :(得分:0)

Javascript将对象作为“引用”传递,所以

var newObject = oldObject; // the old Object() just make a type cast, not necessary here

只需使newObject / oldObject引用相同的对象,然后

newObject.firstMethod = 

也会覆盖oldObject的firstMethod。

为了使newObject成为一个新对象,你需要这样做:

var newObject = {}; //a new object
for(var k in oldObject)
{
     newObject[k]= oldObject[k]; //copy old attrs
}

然后你可以覆盖方法