我正在尝试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
请告诉我错误的地方。
答案 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函数时,采取以下步骤:
- 如果value为null,未定义或未提供,则创建并返回一个新的Object对象,就像使用相同的参数调用标准的内置Object构造函数一样
- 返回ToObject(值)。
醇>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
}
然后你可以覆盖方法