まず、浅いコピーの欠点を見てみましょう。この手口の被害に遭った人は何人いるでしょうか。
var oOriginal = {
memNum: 1, // 数値
memStr: "私は文字列です", // 文字列
memObj: {
test1: "古い値" //
},
memArr をテストします: [ // 配列
"a string", // 配列
の文字列メンバー { // 配列
のオブジェクト メンバー test2: "Try Change me" // テストします
}
]
};
これは、オブジェクトと配列を含む比較的複雑なオブジェクトです。 Prototype の有名な継承関数を使用して、少し複雑にしてみましょう。継承とは言い難いですし、jQueryもカウントされません。
var extend = function(result, source) {
for (ソース内の var key)
result[key] = source[key]
return result;
テスト プログラム:
var oCopy = extend({},oOriginal); //浅いコピー
oCopy .memObj.test1 = "新しい値"; // 問題が発生した場合、元のオブジェクトに反映されます
alert(oOriginal.memObj.test1) // 結果のコピーとオリジナルも一緒に変更されました
oCopy.memArr[1].test2 = "変更されました";
alert(oOriginal.memArr[1].test2) //
元のオブジェクトを変更したくない場合は、オブジェクトと配列を特別に処理する必要があるようです。それらに対処するには、それらを特定する必要があります。次の関数を見てください:
/* *
* タイプの識別 - Situ Zhengmei::cheng 著 (MIT ライセンス)
* http://www.cnblogs.com/rubylouvre/archive/2010/01/20/1652646.html
*/
var is = function (obj,type) {
var toString = Object.prototype.toString,unknown;
return (type === "Null" && obj === null) ||
(タイプ === "未定義" && obj === 未定義) ||
toString.call(obj).slice(8,-1) === タイプ; ;
上記の関数は型の識別に使用されます。typeof は「object」を返します。また、別のドキュメント オブジェクトの Array インスタンスも決定できません。 Object.prototype.toString.call の使用は完璧ではありませんが、アヒル型は簡単にコピーできますが、以前よりもはるかに信頼性が高くなります。
正式に本題に入りましょう。ディープ コピー関数は、値がオブジェクトと配列であるキーと値のペアを特別に処理します。プログラムは、まずターゲット オブジェクトの新しいオブジェクトと配列を作成し、次にコピーします。それらを一層ずつ重ねていきます。 hasOwnProperty が使用されていないことがわかります。つまり、プロトタイプ内の走査可能なプロパティさえも逆さまになっています。配列の場合、for(,,,) ループは使用しません。ループできるのは括弧内の要素だけであり、配列に付加された他の属性はループできません。したがって、for...in の非常に遅いメソッドは次のとおりです。ここではまだ必要です。ディープコピーはすべてのプロパティをチェックし、途中で新しいオブジェクトを作成する可能性があるため、重いメソッドです。用事がない場合は使用しないでください。
コードをコピー コードは次のとおりです:
/**
* type identification - By 司徒正美::cheng (MIT Licensed)
* http://www.cnblogs.com/rubylouvre/archive/2010/03/26/1696600.html
*/
dom.deepCopy = function(result, source){
for(var key in source) {
var copy = source[key];
if(result === copy) continue;//如window.window === window,会陷入死循环,需要处理一下
if(dom.is(copy,"Object")){
result[key] = arguments.callee(result[key] || {}, copy);
}else if(dom.is(copy,"Array")){
result[key] = arguments.callee(result[key] || [], copy);
}else{
result[key] = copy;
}
}
return result;
};
作者:司徒正美