Deep copy of jquey.extension

If you have used JQuery's extension function, you must know something about it.

However, the deep copy of extend is not perfect. Here is an example to analyze with the JQuery source code:

When using extension, if the first parameter passes in true, it means a "deep copy" is required.But this is an incomplete deep copy, as shown in the following example:


  1. function Obj(){  
  2.     this.a = 1;  
  3. }  
  4.   
  5. var obj = new Obj();  
  6.   
  7. var tobeCloned = {o:obj};  
  8.   
  9. var result  = $.extend(true,{},tobeCloned);  
  10.   
  11. tobeCloned.o.a = 2;  
  12.   
  13. console.log(result.o.a);//What is the output?  


As a general understanding of deep copy, the result output should be 1, but the actual result is 2



Let's take a look at the JQuery source code and see:


See the commentary version source for the jquery.extension function (version 1.7)


JQuery source code:

  1. jQuery.extend = jQuery.fn.extend = function() {  
  2.   
  3.     var options, name, src, copy, copyIsArray, clone,  
  4.         target = arguments[0] || {},  
  5.         i = 1,  
  6.         length = arguments.length,  
  7.         deep = false;  
  8.     /* 
  9.     Variable options: Points to a source object. 
  10.     Variable name: An attribute name that represents a source object. 
  11.     Variable src: The original value representing an attribute of the target object. 
  12.     Variable copy: Represents the value of an attribute of a source object. 
  13.     Variable copyIsArray: Indicates whether the variable copy is an array. 
  14.     Variable clone: Represents the modified value of the original value for deep replication. 
  15.     Variable target: Points to the target object, declared temporarily with the first parameter value. 
  16.     Variable i: Indicates the starting subscript of the source object, declared temporarily with the second parameter value. 
  17.     Variable length: Represents the number of parameters used to modify the variable target. 
  18.     Variable deep: Indicates whether to perform deep replication, defaulting to false. 
  19.  
  20.     ps:The source object refers to the object that pays its own value to others; the target object refers to the object assigned by the source object 
  21.     */  
  22.   
  23.     //If the first parameter passes in a Boolean value  
  24.     if ( typeof target === "boolean" ) {  
  25.         deep = target;//Set the deep variable to determine whether to make a deep or a shallow copy  
  26.         target = arguments[1] || {};//Set the target object as the second parameter value.  
  27.         i = 2;//The starting subscript of the source object is set to 2 (that is, the source object is calculated from the third parameter)  
  28.     }  
  29.   
  30.     // Handle case when target is a string or something (possible in deep copy)  
  31.     //Well, the original English explanation is clear  
  32.     if ( typeof target !== "object" && !jQuery.isFunction(target) ) {  
  33.         target = {};  
  34.     }  
  35.   
  36.     //If there is no target object, then the target object is a jquery object  
  37.     if ( length === i ) {  
  38.         target = this;  
  39.         --i;  
  40.     }  
  41.   
  42.     Core part of the copy code  
  43.     for ( ; i < length; i++ ) {//Traversing Source Objects  
  44.         // Only deal with non-null/undefined values  
  45.         if ( (options = arguments[ i ]) != null ) {//options is the source object  
  46.             // Extend the base object  
  47.             for ( name in options ) {//Traversing property names of source objects  
  48.                 src = target[ name ];//Gets the property corresponding to the property name on the target object  
  49.                 copy = options[ name ];//Gets the property corresponding to the property name on the source object  
  50.   
  51.                 //If the copy value copy is equal to the target object target,  
  52.                 //To avoid an infinite loop during deep traversal, the property with the same name of the target object is not overwritten.  
  53.                 if ( target === copy ) {  
  54.                     continue;  
  55.                 }  
  56.   
  57.                 //Recursively merge attribute values from the source object onto the target object  
  58.                 //If it is a deep copy and the object to be copied exists, it is a normal object or an array  
  59.                 //This is a critical judgment, which is the crux of the previous question  
  60.                 //First, the definition of a normal object is: created by'{}'or'new Object'  
  61.                 //Returning to the previous question, the obj of the attribute o object of the target object tobeCloned is neither a normal object nor an array, so the program will not go to the next branch  
  62.                 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {  
  63.                     if ( copyIsArray ) {  
  64.                         //If it is an array  
  65.                         copyIsArray = false;  
  66.                         clone = src && jQuery.isArray(src) ? src : [];  
  67.   
  68.                     } else {  
  69.                         clone = src && jQuery.isPlainObject(src) ? src : {};  
  70.                     }  
  71.   
  72.                     //Recursively copy  
  73.                     target[ name ] = jQuery.extend( deep, clone, copy );  
  74.   
  75.                 } else if ( copy !== undefined ) {  
  76.                 //You will come to this branch, which is a very violent branch that assigns attributes of the source object directly to the source object.  
  77.                 //For the attribute o of the tobeCloned object above, instead of further recursive copying, the reference is directly assigned to the source object  
  78.                 //So when you change the o property of tobeCloned, the o property of the target object is also changed.  
  79.                     target[ name ] = copy;  
  80.                 }  
  81.             }  
  82.         }  
  83.     }  
  84.   
  85.     // Return the modified object  
  86.     return target;  
  87. };  


  88. Author: General Yao
    Links: https://zhuanlan.zhihu.com/p/24570271
    Source: Know
    Copyright belongs to the author.For commercial reprinting, please contact the author for authorization. For non-commercial reprinting, please indicate the source.
Author: General Yao
Link: https://zhuanlan.zhihu.com/p/24570271
Source: Know
Copyright belongs to the author.For commercial reprinting, please contact the author for authorization. For non-commercial reprinting, please indicate the source.

Keywords: JQuery Attribute

Added by adamdyer on Wed, 13 May 2020 19:49:58 +0300