0

我正在尝试 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

4 回答 4

1

TL;DR:那(很可能)是您的代码中的一个错字:它应该是这样写的:

var newObject = Object.create(oldObject);

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

var newObject = Object(oldObject);

... 不创建新对象:相反newObject,变量成为对同一对象引用的存储引用oldObject。这是标准所说的:

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

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

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-,基本上所有现代浏览器都支持它)。它不是 ES5 标准的一部分,但它可能会成为 ES6 的一部分。

但我猜克罗克福德实际上是这样的意思:

var newObject = Object.create(oldObject);

...因此,再次引用标准,“创建具有指定原型的新对象”。

于 2013-11-14T07:14:58.397 回答
1

如果您将 Object 构造函数作为函数调用,它会执行类型转换(在这种情况下什么都不会,因为参数已经是一个对象)。(如果你将它作为构造函数调用并传递给它一个对象,就像你在那里所做的那样,那么它只会返回那个对象)。

newObject不是一个新对象,它是同一个对象。因此,任何对 的修改newObject也是对 的修改oldObject

可能你想要:

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

而不是Object()打电话。

于 2013-11-14T07:13:42.220 回答
0

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

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

那应该可以解决您的问题。看看这个以获得更深入的答案:如何正确克隆 JavaScript 对象?

编辑

此外,从上面的线程中,一个非 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;
}
于 2013-11-14T07:16:46.890 回答
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
}

然后你可以覆盖方法

于 2013-11-14T07:17:34.457 回答