On JavaScript object Copy implementation and question example

Source: Internet
Author: User
Tags arrays extend shallow copy jquery library

In the actual programming process, sometimes we will encounter a situation: When you have an object A, at a certain moment, a has already saved the corresponding attribute value, and the values themselves are valid, this time may require a exactly the same object B, and when the value of the property in B changes, The property values in a are not affected and can be understood to be independent of A and B, but the initialization of B is not the initialization of the object we normally create, and B's initialization data is entirely from a.

First, shallow copy

We typically do this when we need to copy an object to another object.


function Shadowcopy (source,target) {
var target=target| |    {};
for (var i in source)
{
target[i]=source[i];
return
target;
}
var a={name: ' Lily ', age:19};
var b=shadowcopy (a);//b={name: ' Lily ', age:19}


The problem with a shallow copy is that if the parent object's property equals an array or another object, the child object actually gets just a memory address, not a real copy, and the child object's corresponding property changes when the parent object's array or object property changes

function Shadowcopy (source,target) {
var target=target| |    {};
for (var i in source)
{
target[i]=source[i];
return
target;
}
var a={name: ' Lily ', hobbies:[' Music ', ' Sport ']};
var b=shadowcopy (a);//b={name: ' Lily ', hobbies:[' Music ', ' Sport '}
a.hobbies.push (' Read ');//b={name: ' Lily ', hobbies:[' Music ', ' Sport ', ' Read '}


Second, deep copy

In order to solve the above problem, we need to make a deep copy of the object's array and object properties. Its implementation is not difficult, as long as the recursive call "shallow copy" on the line

Function deepcopy (source,target) {    var target=target| |
{};     for (var i in source)     {         if (typeof source[i] ===  ' object ') {             target[i] =  (source[i].constructor === array )
 ? [] : {} ;
            deepcopy (Source[i],target[i]);         }else{         
   target[i]=source[i];         }          return 
Target }              var a={name: ' Lily ', Hobbies
: [' Music ', ' Sport ']}; Var b=deepcopy (a);//b={name: ' Lily ', Hobbies:[' music ', ' Sport ']} a.hobbies.push (' read ')//b={name: ' Lily ', hobbies:[' music ', ' sport ', ' read ']},b={name: ' Lily ', hobbies:[' Music ', ' Sport ']}


One problem with this code is that when a self reference exists in the object being copied, the program falls into an infinite loop

var a={name: ' Lily '};
A.obj=a;
Deepcopy (a);

When the Chome console runs, the following prompts

Rangeerror:maximum Call stack size exceeded

In order to solve the problem of self reference, add the judgment logic to copy

Function deepcopy (source,target) {    var target=target| |
{};     for (var i in source)     {                 //prevent self-referencing          if (source[i] === source )         
    continue;         if (typeof source[i] ===  ' object ') {             target[i] =  (source[i].constructor 
=== array )  ? [] : {} ;
            deepcopy (Source[i],target[i]);         }else{         
   target[i]=source[i];         }          return target;
}              var a={name: ' Lily '};
A.obj=a; Var b=deepcopy (a);//b={name: ' Lily '}


Three, jquery copy implementation

Online There are many analysis of the jquery extend methods, there are not understand can go to search read

Paste an analysis of the source code

Jquery.extend = jquery.fn.extend = function ()  {    var src,  copyisarray, copy, name, options, clone,          target = arguments[0] | |  {},         i = 1,          length = arguments.length,         deep =
 false;     // handle a deep copy situation     if   ( typeof target ===  "boolean"  )  {      
  deep = target;         target = arguments[1] | |
 {};         // skip the boolean and the  Target        &Nbsp;i = 2;     }     // handle case when target is a  string or something  (possible in deep copy)     if   ( typeof target !==  "Object"  && !jquery.isfunction (target)  )  {        target = {};     }      // extend jquery itself if only one argument is  passed     if  ( length === i )  {   
     target = this;
        --i; &NBSP;&NBSP;&NBSP;&NBSP}     for  ( ; i < length; i++  )  {        // only deal with non-null/ UndefiNed values         if    (options = arguments[ &NBSP;I&NBSP]  != null )  {             // extend the base object              for  ( name in options )  {     
           src = target[ name ];                 copy =
 options[ name ];                 //  Prevent never-ending loop                  if  ( target === copy )  {&NBSP;&NBSP;&NBSP;&NBSP;&NBsp;               continue;                 }                  // recurse if  we ' Re merging plain objects or arrays                  if  ( deep && copy & &  ( jquery.isplainobject (copy)  | |   (Copyisarray = jquery.isarray (copy)  )  )  {                     if  ( copyisarray  )  {                         copyisarray = falsE                          clone = src && jquery.isarray (SRC)  ?
 src : [];                      } else {                         clone = src && 
Jquery.isplainobject (SRC)  ? src : {};                      }                      // never move original objects, clone them                      target[ name ] = 
Jquery.extend ( deep, clone, copy );                 // don ' t  bring in undefined values           
      } else if  ( copy !== undefined )  {                   
  target[ name ] = copy;                 }   
          }         } &NBSP;&NBSP;&NBSP;&NBSP}     // return the modified object      return&nbsP;target; };


Iv. jquery Implementation Questions

When reading the jquery code above, there is a place for questions, and the query code is as follows

Prevent never-ending Loop
if (target = = copy) {
continue;
}

The


notes that in the Extend method, to prevent an infinite loop, there is a logic for this copy operation to be transferred when the target object equals the Copy object. Where the Copy object is the Property object of the Options object.

The question is, why do you want to compare the target object with the Copy object? Shouldn't you be comparing the Copy object and the options object?

With this in doubt, execute

var a={name in a page console that has been introduced into the jquery library: ' Lily '};
A.obj=a;
var b={};
$.extend (true,b,a);
Rangeerror:maximum Call stack size exceeded

You can see that the Extend method does not prevent an infinite loop when there is a self referencing property in a object

then judge target = = = What role does copy play?

var a={name: ' Lily '};
var b={age:19};
A.obj=b;
$.extend (true,b,a);
//At this time b={age:19, name: "Lily"}

Remove the judge = = Copy will fall into an infinite loop? It's not actually.

var a={name: ' Lili '};
var b={age:19};
A.obj=b;
Deepcopy (true,b,a);
//b=object {age:19, Name: "Lili", Obj:object}
//(where Object is b

here deepcopy is the Extend method of jquery that I remove from the above judgment logic, You have implemented a copy of the

Function deepcopy ()  {    var src, copyisarray, copy, name,  options, clone,         target = arguments[0]  | |  {},         i = 1,          length = arguments.length,         deep =
 false;     // handle a deep copy situation     if   ( typeof target ===  "boolean"  )  {      
  deep = target;         target = arguments[1] | |
 {};         // skip the boolean and the 
Target         i = 2;    &nBSP;}     // handle case when target is a string or  something  (possible in deep copy)     if  ( typeof  target !==  "Object"  && !jquery.isfunction (target)  )  {   
     target = {};     }     // extend jquery itself if only  one argument is passed     if  ( length === i  )  {        target = this;      
   --i; &NBSP;&NBSP;&NBSP;&NBSP}     for  ( ; i < length; i++  )  {        // only deal with non-null/ Undefined values         if  (  (options = arguments[ i ])  != null )  {            // Extend the  Base object             for  ( name  in options )  {            
    src = target[ name ];                 copy =
 options[ name ];                                   /**                  // Prevent  Never-ending loop                 if  ( options ===  copy )  {              
      continue;                 }                  */                 // recurse if we ' re  merging plain objects or arrays                  if  ( deep && copy &&   ( isplainobject (copy)  | |   (Copyisarray =isarray (copy)  )  )  {                     if  ( copyIsArray )  {                         
copyisarray = false;                          clone = src && isarray (SRC)  ? src
 : [];                      } else {                         clone = src && 
Isplainobject (SRC)  ? src : {};                      }                     // Never  Move original objects, clone them                      target[ name ] =deepcopy (
 deep, clone, copy );                 // don ' t  bring in undefined values           
      } else if  ( copy !== undefined )  {                   
  target[ name ] = copy;                 }                        }     }  
   // return the modified object     return target;
}; Var isstring=function (obj) {    return object.prototype.tostring.call (obj)  =
==  ' [object string] ';
}; Var isarray=function (obj) {    return object.prototype.tostring.call (obj)  ==
=  ' [Object array] ';
}; Var isplainobject=function (obj) {    return object.prototype.tostring.call (obj)
 ===  ' [Object object] ';
} var a={name: ' Lili '};
var b={age:19};
A.obj=b; Deepcopy (True,b,a);


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.