Also to talk about JS shallow copy and deep copy

Source: Internet
Author: User
Tags shallow copy

1. Shallow copy vs deep copy

The copy in this article can also be referred to as a copy, which in this article is considered to be the same meaning of copy and copy. In addition, this article only discusses the replication of complex data types in JS (Object,array, etc.), does not discuss the basic data types (Null,undefined,string,number and Boolean), these types of values themselves are stored in the stack memory ( The actual value of the string type is stored in heap memory, but JS handles string as the base type, and there is no case of reference value.

Both shallow and deep replication can be used to regenerate a copy of an existing object, but an instance of the object is stored in the heap memory and then manipulated by a reference value, and there are two cases when copying it: Copy the reference and copy the instance, which is the difference between shallow copy and deep copy.

Shallow copy: a shallow copy is a copy of a reference, and the copied reference is an instance of the same object that affects each other's actions

deep copy: a deep copy is not a simple copy of a reference, but instead allocates memory in the heap and creates a new copy of all the properties of the source object instance to ensure that the reference graph of the deeply copied object does not contain any objects on the original object or object graph, and that the copied object is completely isolated from the original object

In the definition of deep replication, deep replication requires that if the source object has an object attribute, recursive replication is required to ensure that the copied object is completely isolated from the source object. However, there is also the granularity between shallow copy and deep copy, and also the Extend method of jquery, which is called "shallow copy" when the depth parameter is false, which replicates only one level: that is, if an object attribute exists in the source object, the same object is also referenced on the copied object. This does not conform to the requirements of deep replication, but it deepens the granularity of replication compared to simple replication references.

2. Shallow copy

This article thinks that shallow copy is simple reference copy, this is relatively simple, the following code is simple to understand:

var src = {        name: "src"    }    //Copy the application of SRC object    var target = src;    Target.name = "target";    Console.log (src.name);   Output target

The target object is simply a copy of the reference value of the SRC object, so the change to target will also affect SRC.

3. Deep copy

Deep replication is a bit more complicated, let's start with a few more simple scenarios:

Slice and Concat methods for 3.1 array

Both the slice and concat methods of the array return a new array instance, but the two methods do not perform a deep copy of the object elements in the array, but simply copy the references, so the two methods are not really deep copies, as understood by the following code:

    var array = [n/a];    var array_shallow = array;    var array_concat = Array.concat ();    var array_slice = array.slice (0);    Console.log (Array = = = Array_shallow);   True    console.log (array = = = Array_slice);     False    console.log (array = = = Array_concat);    False

As you can see, concat and slice return different array instances, which are different from the direct copy of the reference.

    var array = [1, [+ +], {name: "array"}];    var array_concat = Array.concat ();    var array_slice = array.slice (0);    Change the value of the array element in the Array_concat    array_concat[1][0] = 5;    Console.log (array[1]);    [5,2,3]    Console.log (array_slice[1]);  [5,2,3]    //Change the value of the object element in the Array_slice    array_slice[2].name = "Array_slice";    Console.log (array[2].name);   Array_slice    Console.log (array_concat[2].name);//array_slice

The output from the code shows that concat and slice are not really deep copies, the object elements in the array (Object,array, etc.) just copy the reference

3.2 Parse and stringify for JSON objects

The JSON object is the new type introduced in ES5 (the supported browser is ie8+), and the JSON object parse method can deserialize the JSON string into a JS object, and the Stringify method can serialize the JS object into a JSON string, and with these two methods, You can also implement a deep copy of an object.

    var Source = {        Name: "Source",        child:{            Name: "Child"        }    }    var target = Json.parse ( Json.stringify (source));    Change the Name property of target    target.name = "target";    Console.log (source.name);   SOURCE    Console.log (target.name);   Target    //change Target's child    Target.child.name = "target Child";    Console.log (source.child.name);  Child    Console.log (target.child.name);  Target Child

As you can see from the output of the code, the copied target is completely isolated from the source and does not affect each other.

This method is simpler to meet basic deep replication requirements, and can handle all data types that the JSON format can represent, but cannot be deep copied (and will lose the corresponding values directly) for regular expression types, function types, and so on, and if a circular reference exists in the object, it cannot be handled correctly

The method of extend replication in 3.3 jquery

The Extend method in jquery can be used to extend an object, and this method can pass in a parameter: Deep (true or false), which indicates whether to perform a dark copy (if deep copy would perform recursive replication), let's first look at the source code in jquery (1.9.1)

Jquery.extend = JQuery.fn.extend = function () {var options, name, SRC, copy, copyisarray, Clone,target = Arguments[0] | | { },i = 1,length = Arguments.length,deep = false;//Handle a deep copy situationif (typeof target = = = "Boolean") {deep = t Arget;target = Arguments[1] | | {};//Skip the Boolean and the Targeti = 2;} Handle case when Target was a string or something (possible in deep copy) if (typeof target!== "Object" &&!jqu Ery.isfunction (target) {target = {};} Extend JQuery itself if only one argument is passedif (length = = i) {target = this;--i;} for (; i < length; i++) {//-deal with non-null/undefined valuesif (options = arguments[i]! = NULL) {//EXT End the base objectfor (name in options) {src = target[name];copy = options[name];//Prevent never-ending loopif (t Arget = = = copy) {continue;} Recurse if we ' re merging plain objects or arraysif (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 themtarget[name] = Jquery.extend (deep, clone, copy);//Don ' t bring in undefined Values} else if (copy!== undefined) {target[name] = copy;}}} Return the modified objectreturn target;};

This method is one of the important basic methods in jquery, which can be used to extend the JQuery object and its prototype, as well as the key method of writing jquery plug-in, in fact, the basic idea of this method is to perform recursive replication if it encounters the attribute of array or object. This also leads to date,function, such as reference types, that jquery extend cannot support. Here's an overview of this approach:

(1) 第1-6 defines some local variables, which will be used later, in the way that the local variables that may be used in the function are first uniformly defined in the form of "single var" mode

(2) The 第9-13 line is used to correct the deep parameters, this method of jquery is to pass the deep as the first parameter, so here is to determine whether the first parameter is a Boolean type, if so, then adjust the target and I value, An I value indicates the index of the first source object

(3) 第17-19 fixed the target object, if the target's typeof operator returned is not an object, is not a function, then the target passed in is a basic type, it needs to be fixed to an empty object literal {}

(4) 第22-25 line to handle the case where only one parameter is passed, this method extends the jquery object or its prototype object in the case of passing in a parameter

(5) Starting from 27 lines, use for in to traverse the list of source objects, because the Extend method can pass in multiple source objects, take out each source object, and then nest a for in loop to traverse the properties of a source object

(6) The 32nd row takes out the current property of target and the current property of source, and the main function of 35-38 rows is to prevent the dead loop when deep traversal. However, if the source object itself has a circular reference, the Extend method will still report a stack overflow error

(7) If the 41st line is used to handle the case of a deep copy, a recursive deep copy is required if the passed in depth parameter is true and the current Source property value is Plainobject (object created using object literal or new object) or array.

(8) 第42-48 the SRC is processed according to whether the type of copy is Plainobject or array: If copy is an array, then SRC is rewritten as an empty array if it is not an array; if copy is Chainobject, So if SRC is not chainobject, rewrite it as {}

(9) If the IF condition of the 41 row is not set, then the SRC attribute of target is overwritten with copy directly

The Extend method of jquery implements deep replication using the basic recursive approach, but this method also fails to handle the problem of circular references within the source object, and does not achieve a true deep copy for values of type date, function, etc. However, these types of values are typically directly overwritten when redefined, so they are not affected by the source object, and are therefore partly consistent with deep copy conditions

3.4 Implement a copy method yourself

According to the above ideas, the implementation of a copy, you can pass in the deep parameter to indicate whether to perform a dark copy:

 Util as an auxiliary module for determining the specific type of variable var util = (function () {var class2type = {}; ["Null", "Undefined", "number", "Boolean", "String", "Object", "function", "Array", "RegExp", "Date"].foreach (Function (        Item) {class2type["[object" + Item + "]"] = Item.tolowercase ();        }) function Istype (obj, type) {return GetType (obj) = = = Type; } function GetType (obj) {return class2type[object.prototype.tostring.call (obj)] | |        "Object";    } return {istype:istype, Gettype:gettype}}) (); function Copy (obj,deep) {//If obj is not an object, then the direct return value is OK if (obj = = = NULL | | typeof obj!== "Object") {RE        Turn obj; }//define the desired local face change, adjust the type of the target according to the type of obj var i, target = Util.istype (obj, "array")?        []: {},value,valuetype;            for (i in obj) {value = Obj[i];        ValueType = Util.gettype (value); Recursive replication is performed only if deep copy is explicitly performed, and the current value is an array or an object, if (depth && (VALuetype = = = "Array" | |            ValueType = = = "Object")) {Target[i] = copy (value);            }else{Target[i] = value;    }} return target; }

  

  

Also to talk about JS shallow copy and deep copy

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.