これらすべての優れた回答の後、これ以上言うことはありません。ECMAScript 5 仕様に基づいて説明します。
また、回答の最後にある deepclone 関数。
ES5仕様で定義されているように、
11.13.1 単純代入 ( = )
プロダクション AssignmentExpression : LeftHandSideExpression = AssignmentExpression は次のように評価されます。
- lref を LeftHandSideExpression の評価結果とします。
- AssignmentExpression を評価した結果を rref とします。
- rval とする
GetValue(rref)
。
- 次の条件がすべて真の場合、SyntaxError 例外をスローします。
- Type(lref) is Reference is true
- 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
が保持され、 5 に挿入されます。
§8.7.2 (ここでも 4b がPutValue(V,W) //V==lref , W==rval
興味深い部分です) が登場します。
注: W は値ではなく、割り当てたいオブジェクトへの参照です。
4. IsPropertyReference(V) の場合
- (b) base を this 値として使用して put 内部メソッドを呼び出し、プロパティ名に GetReferencedName(V)、値に W、Throw フラグに IsStrictReference(V) を渡します。
あなたのケースでわかるように、オブジェクトへの参照である atmの値は、いわば への参照である の結果に置き換えられます。b
[6, 7, 8]
GetValue(rref)
[1, 2, 3];
でも
どうやら深いクローン機能を探しているようです
これが1つです。
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のデモ
.clone(levelOfDeepness)
それを使用するには、オブジェクトまたは配列を呼び出すだけです
注: 簡単にするために Objects プロトタイプを使用しました。これは、.clone
Object 要素と Array 要素を複製しながら直接呼び出すことができるためです (単一の関数で型チェック バリアントよりもパフォーマンスが向上します)。