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:
- function Obj(){
- this.a = 1;
- }
- var obj = new Obj();
- var tobeCloned = {o:obj};
- var result = $.extend(true,{},tobeCloned);
- tobeCloned.o.a = 2;
- 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:
- jQuery.extend = jQuery.fn.extend = function() {
- var options, name, src, copy, copyIsArray, clone,
- target = arguments[0] || {},
- i = 1,
- length = arguments.length,
- deep = false;
- /*
- Variable options: Points to a source object.
- Variable name: An attribute name that represents a source object.
- Variable src: The original value representing an attribute of the target object.
- Variable copy: Represents the value of an attribute of a source object.
- Variable copyIsArray: Indicates whether the variable copy is an array.
- Variable clone: Represents the modified value of the original value for deep replication.
- Variable target: Points to the target object, declared temporarily with the first parameter value.
- Variable i: Indicates the starting subscript of the source object, declared temporarily with the second parameter value.
- Variable length: Represents the number of parameters used to modify the variable target.
- Variable deep: Indicates whether to perform deep replication, defaulting to false.
- 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
- */
- //If the first parameter passes in a Boolean value
- if ( typeof target === "boolean" ) {
- deep = target;//Set the deep variable to determine whether to make a deep or a shallow copy
- target = arguments[1] || {};//Set the target object as the second parameter value.
- i = 2;//The starting subscript of the source object is set to 2 (that is, the source object is calculated from the third parameter)
- }
- // Handle case when target is a string or something (possible in deep copy)
- //Well, the original English explanation is clear
- if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
- target = {};
- }
- //If there is no target object, then the target object is a jquery object
- if ( length === i ) {
- target = this;
- --i;
- }
- Core part of the copy code
- for ( ; i < length; i++ ) {//Traversing Source Objects
- // Only deal with non-null/undefined values
- if ( (options = arguments[ i ]) != null ) {//options is the source object
- // Extend the base object
- for ( name in options ) {//Traversing property names of source objects
- src = target[ name ];//Gets the property corresponding to the property name on the target object
- copy = options[ name ];//Gets the property corresponding to the property name on the source object
- //If the copy value copy is equal to the target object target,
- //To avoid an infinite loop during deep traversal, the property with the same name of the target object is not overwritten.
- if ( target === copy ) {
- continue;
- }
- //Recursively merge attribute values from the source object onto the target object
- //If it is a deep copy and the object to be copied exists, it is a normal object or an array
- //This is a critical judgment, which is the crux of the previous question
- //First, the definition of a normal object is: created by'{}'or'new Object'
- //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
- if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
- if ( copyIsArray ) {
- //If it is an array
- copyIsArray = false;
- clone = src && jQuery.isArray(src) ? src : [];
- } else {
- clone = src && jQuery.isPlainObject(src) ? src : {};
- }
- //Recursively copy
- target[ name ] = jQuery.extend( deep, clone, copy );
- } else if ( copy !== undefined ) {
- //You will come to this branch, which is a very violent branch that assigns attributes of the source object directly to the source object.
- //For the attribute o of the tobeCloned object above, instead of further recursive copying, the reference is directly assigned to the source object
- //So when you change the o property of tobeCloned, the o property of the target object is also changed.
- target[ name ] = copy;
- }
- }
- }
- }
- // Return the modified object
- return target;
- };
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.
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.