在所有这些很棒的答案之后,真的没有更多可说的了,所以这里有一个基于 ECMAScript 5 规范的解释。
答案末尾还有一个深度克隆功能。
正如 ES5 规范中定义的那样,
11.13.1 简单赋值 (=)
产生式 AssignmentExpression : LeftHandSideExpression = AssignmentExpression 计算如下:
- 令 lref 为评估 LeftHandSideExpression 的结果。
- 令 rref 为评估 AssignmentExpression 的结果。
- 设 rval 为
GetValue(rref)
。
- 如果以下条件都为真,则抛出 SyntaxError 异常:
- 类型(lref)是参考是真的
- IsStrictReference(lref) 为真
- Type(GetBase(lref)) 是环境记录
- GetReferencedName(lref) 是“eval”或“arguments”
- 打电话
PutValue(lref, rval)
。
- 返回 rval。
所以当我们到达第3点并且rref
是一个对象时发生了什么,是
§8.7.1(In 的第 4b 节GetValue(V) //V==rref
是有趣的点)
4. 如果 IsPropertyReference(V),那么
- (b) 返回使用 base 作为 this 值调用 get 内部方法的结果,并为参数传递 GetReferencedName(V)。
现在此时rval
持有对 Object 的引用,然后将其放入5。
§8.7.2(同样PutValue(V,W) //V==lref , W==rval
是有趣的部分 4b)开始发挥作用。
注意:W 是 atm 对要分配的对象的引用,而不是值
4. else if IsPropertyReference(V),则
- (b) 使用 base 作为 this 值调用 put 内部方法,并传递 GetReferencedName(V) 作为属性名称,W 作为值,IsStrictReference(V) 作为 Throw 标志。
正如您在您的情况下看到的那样,它的值是b
atm对 Object的引用[6, 7, 8]
被替换为可以说的结果GetValue(rref)
,这是对Object 的引用[1, 2, 3];
然而
显然你正在寻找一个深度克隆功能
这是一个。
Object.defineProperty(Object.prototype, "clone", {
value: function (deep) {
var type = Object.prototype.toString.call(this).match(/^\[object (.+?)\]$/)[1];
if (type !== "Object") {
return this.valueOf;
}
var clone = {};
if (!deep) {
for (var prp in this) {
clone[prp] = this[prp];
}
} else {
for (var prop in this) {
if (typeof this[prop] !== "undefined" && this[prop] !== null)
clone[prop] = (typeof this[prop] !== "object" ? this[prop] : this[prop].clone((typeof deep == "boolean" ? deep : (deep - 1))));
else
clone[prop] = "";
}
}
return clone;
},
enumerable: false
});
Object.defineProperty(Array.prototype, "clone", {
value: function (deep) {
var clone = [];
if (!deep) clone = this.concat();
else this.forEach(function (e) {
if (typeof e !== "undefined" && e !== null)
clone.push((typeof e !== "object" ? e : e.clone((deep - 1))));
else
clone.push("");
});
return clone;
},
enumerable: false
});
var a = [1, [2, { a: 3 } ], 4];
var b = a.clone(Infinity);
a[1][1]["a"] = "cloned";
console.log(a[1][1]["a"], b[1][1]["a"]); //"cloned" , 3
还有一个关于JSBin的Demo
要使用它,只需调用.clone(levelOfDeepness)
一个对象或数组
注意:为了简单起见,我使用了 Objects 原型,因为我可以.clone
在克隆它们时直接调用 Object 和 Array 元素(比单个函数中的类型检查变体提高性能)