Record a common face question, a deep clone of the object in JavaScript, reprinted from: http://www.2cto.com/kf/201409/332955.html
Today we will talk about a common written test, interview questions, JS object in depth cloning. Turned over this topic, in many places, has been an old problem, but the annual school recruit always test, in fact, think, this topic to examine the knowledge point is quite many, especially the basic knowledge of the examination. Well, gossip doesn't say much, get to the point.
First, the object of JS refers to the cloning of objects, must say the concept of the object. The data types in JS are divided into two main categories: primitive type and object type. (1) Primitive types include: Numeric, String, Boolean, null, undefined (the latter two are special primitive values, not detailed here, my previous blog has talked about some) (2) object types include: An object is a collection of properties, Of course there are two special objects----function (a class object in JS), an array (an ordered collection of key values). Okay, now that the objects are in these two categories, the two types are very different when replicating clones. The original type stores the actual data of the object, and the object type stores the object's reference address (the actual contents of the object are stored separately, in order to reduce the data overhead usually stored in memory). PS: Here, you know, the object's prototype is also a reference object, it puts the methods and properties of the prototype in memory, through the prototype chain to point to the memory address. Second, the concept of cloning a shallow clone: The original type is a value pass, and the object type is still passed as a reference. Deep cloning: All elements or attributes are completely copied, completely detached from the original object, meaning that all modifications to the new object are not reflected in the original object. Three, shallow cloning performance 1, the original type look at the following section of code:
// The performance of a numeric clone a= "1" ; var b=a;b = "2" ;console.log (a); // Console.log (b); //
// string cloning performance c= "1" ; var d=c;d = "2" ;console.log (c); // Console.log (d); //
// representation of String clones var x=true; var y=x;y=false; console.log (x); // trueconsole.log (y); // false
As you can see from the code above, the original type can still get the correct result even if we use normal cloning, because the original type stores the actual data of the object.
2. Object type the first class object, of course, is the object type, but the cloning of the function is done by a shallow clone.
var m=function() {alert (1);}; var n=m;n=function() {alert (2);}; Console.log (M ()); // 1console.log (n ()); // 2
As you can see, the function is cloned directly from the normal assignment and does not affect the previous object. The reason is that the cloning of a function creates a separate space in the memory and does not affect each other. Well, after saying this special "connections", let's talk about the ordinary "players". To facilitate subsequent code performance, I define a complex object type Operson here. Here's a look at the harm of shallow copy of object type:
varoperson={oname:"Rookiebob", Oage:"18", oaddress:{Province:"Beijing"}, ofavorite:["Swimming", {reading:"Book of History"}], Skill:function() {Console.log ("Bob is coding"); }};functionClone (obj) {varresult={}; for(Keyinchobj) {Result[key]=Obj[key]; } returnresult;}varonew=Clone (Operson); Console.log (oPerson.oAddress.province);//BeijingOnew.oaddress.province= "Shanghai"; Console.log (oPerson.oAddress.province);//Shanghai
Through the above code, you can see, after the object cloning, I modified onew address, found that the original object Operson has also been modified. This indicates that the cloning of the object is not thorough enough, that is to say deep cloning failed! The implementation of deep cloning in order to ensure that all properties of an object are copied to, we must know that if the resulting element is still an object or array after the For loop, you need to loop again until the element is the original type or function. To get the type of the element, we define a general function that returns the type of the incoming object.
// returns the class of any object passed to him function IsClass (o) { if(o===nullreturn "null"; if return "Undefined"; return Object.prototype.toString.call (o). Slice (8,-1);}
PS:Object.prototype.toString.call (o) can directly return the class property of an object, such as the string "[object class]", by intercepting class and knowing what type of object is passed in. Of course there are two questions to explain: (1) Why not use the ToString method directly? This is to prevent the ToString method in the object from being overridden, in order to properly call the ToString () version, the Function.call () method must be called indirectly (2) Why not use TypeOf to determine the type directly? Because for array, using typeof (Array) returns an object, so the correct array cannot be obtained, and the subsequent cloning of the array will have a fatal problem. Here's the real deep clone.
//Deep CloningfunctionDeepclone (obj) {varresult,oclass=isclass (obj); //determine the type of result if(oclass=== "Object") {result={}; }Else if(oclass=== "Array") {result=[]; }Else{ returnobj; } for(Keyinchobj) { varcopy=Obj[key]; if(IsClass (copy) = = "Object") {Result[key]=arguments.callee (copy);//Recursive invocation}Else if(IsClass (copy) = = "Array") {Result[key]=Arguments.callee (copy); }Else{Result[key]=Obj[key]; } } returnresult;}//returns the class of any object passed to himfunctionIsClass (o) {if(o===NULL)return"Null"; if(o===undefined)return"Undefined"; returnObject.prototype.toString.call (o). Slice (8,-1);}varoperson={oname:"Rookiebob", Oage:"18", oaddress:{Province:"Beijing"}, ofavorite:["Swimming", {reading:"Book of History"}], Skill:function() {Console.log ("Bob is coding"); }};//Deep Clone an objectvaronew=Deepclone (Operson); onew.ofavorite[1].reading= "Picture"; Console.log (onew.ofavorite[1].reading);// PictureConsole.log (operson.ofavorite[1].reading);// history BookoNew.oAddress.province= "Shanghai"; Console.log (oPerson.oAddress.province);//BeijingConsole.log (oNew.oAddress.province);//Shanghai
As you can see from the code above, the deeply cloned object can be completely detached from the original object, and any modifications we make to the new object will not be reflected in the original object, so deep cloning is implemented. One thing to note here is: why should the result of deepclone this function be judged by type? Here is a situation, if your result is directly {} object, I passed in an array, and after you have copied it, it becomes an object.
//Deep CloningfunctionDeepclone (obj) {varresult={},oclass=isclass (obj); //if (oclass=== "Object") { //result={}; //}else if (oclass=== "Array") { //result=[]; //}else{ //return obj; // } for(Keyinchobj) { varcopy=Obj[key]; if(IsClass (copy) = = "Object") {Result[key]=Arguments.callee (copy); }Else if(IsClass (copy) = = "Array") {Result[key]=Arguments.callee (copy); }Else{Result[key]=Obj[key]; } } returnresult;}functionIsClass (o) {if(o===NULL)return"Null"; if(o===undefined)return"Undefined"; returnObject.prototype.toString.call (o). Slice (8,-1);}//cloning an arrayvarArr=["A", "B", "C"];varonew=Deepclone (arr); Console.log (onew);//Object {0: "A", 1: "B", 2: "C"}
Deep cloning of objects in JavaScript