Let’s first look at the flaws of shallow copying. How many people have fallen victim to this trick?
var oOriginal = {
memNum: 1, / / number
memStr: "I am a string", // string
memObj: {
test1: "Old value" // we'll test
},
memArr: [ / / array
"a string", // string member of array
{ // object member of array
test2: "Try changing me" // we'll test
}
]
};
This is a relatively complex object, which contains objects and arrays. Let's use Prototype's famous inheritance function to complicate it a little bit. It's hard to say that it's an inheritance, and jQuery doesn't count either.
var extend = function(result, source) {
for (var key in source)
result[key] = source[key];
return result;
}
Test program:
var oCopy = extend({},oOriginal); // Shallow copy
oCopy .memObj.test1 = "New value"; // If a problem occurs, it will be reflected to the original object
alert(oOriginal.memObj.test1); // The result copy and the original have been modified together
oCopy. memArr[1].test2 = "I am changed";
alert(oOriginal.memArr[1].test2); // Also hit
]
It seems that if you don’t want to modify the original Objects, we need to deal with objects and arrays specially. In order to deal with them, we must identify them. Look at the following function:
The code is as follows:
/**
* type identification - By Situ Zhengmei::cheng (MIT Licensed)
* http://www.cnblogs.com/rubylouvre/archive/2010/01/20/1652646.html
*/
var is = function (obj,type) {
var toString = Object.prototype.toString,undefined;
return (type === "Null" && obj === null) ||
(type === "Undefined" && obj === undefined ) ||
toString.call(obj).slice(8,-1) === type;
};
The above function is used for type identification. typeof is unreliable. Array will return "object". Neither does instanceof. It cannot determine the Array instance of another document object. Although using Object.prototype.toString.call is not perfect, duck type is easy to copy, but it is much more reliable than before.
Let’s officially enter the topic. Our deep copy function will specially handle key-value pairs whose values are objects and arrays. For them, the program will first create a new object and array for the target object, and then copy them layer by layer. We can see that it does not use hasOwnProperty. In other words, even the traversable properties in the prototype are turned upside down. For arrays, we don't use the for(,,,) loop. It can only loop through the elements in parentheses and cannot loop through other attributes attached to the array. Therefore, the extremely slow method of for...in is still needed here. Since deep copy checks all properties and may create new objects in the middle, it is a heavy method. Don't use it if you have nothing to do.
The code is as follows:
/**
* 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;
};
作者:司徒正美