Shallow copy shallowcopy and deep copy deepcopy in JavaScript

Source: Internet
Author: User
Tags shallow copy

Copy, in JS, is divided into shallow copy and deep copy. How are these two differentiated? And how is it achieved?

The distinction between shades of a copy

First of all, in JS, is divided into basic data types and complex data types,

Underlying data type: number, String, Boolean, undefined, null, Sysmbol

Complex data types: Object, Array, Function, date, and so on

The underlying data type value, stored in the stack and copied, will re-create the same space in the stack to store the data. For complex data types, values are stored in the heap, where the reference address of the value is stored in the stack. A depth copy, only for complex data types.

A shallow copy of the shallowcopy is a bit-wise copy of an object. Creates a new object that has an exact copy of the original object. If any field of an object is a reference to another object, only the reference address is copied, that is, only the memory address is copied, not the object itself, and the old or new object shares the same block of heap memory. Change one of the objects and the other will also be affected. If there are changes, the original data is lost.

Deep copy deepcopy, copy a brand-new object instance, the new object and the original object does not share memory, the operation does not affect each other.

Simple point to distinguish,

shallow copy copy reference;

Deep copy copy instance.

Shallowcopy shallow copy Implementation mode 1. Assign value

First of all, the simple assignment situation,

var o1 = { a : 1, b : 2 }var o2 = o1console.log(o2 === o1) // trueo1.a = 2console.log(o1) // {a: 2, b: 2}console.log(o2) // {a: 2, b: 2}

Assignment, which is a reference to an object's address, changes the value of an object, and the value of another copied object changes, so this is a shallow copy.

2. Array.concat ()

The Concat method is used to combine two or more arrays. The method does not change an existing array, but simply returns a copy of the concatenated array.

var o1 =  [1, [2], 3]var o2 = o1.concat([]) // 这里会返回一个o1对象的浅拷贝对象console.log(o2) //  [1, [2], 3]console.log(o1 === o2) // false

The O2 array is a new array. If you change the O1 array object, will it affect the O2 array object?

o1[0] = 11console.log(o1) // [11, [2], 3]console.log(o2) // [1, [2], 3]

In this case, the O2 array value is not changed. This is because the first element in O2 and O1 is not the same memory address.

o1[1][0] = 22console.log(o1) // [11, [22], 3]console.log(o2) // [1, [22], 3]

Instead of modifying the value of the reference in the O1 variable, the O2 array value changes as well. This means that the second element in O2 and the second element in O1 refer to the same memory address.

According to the above note, it can be concluded that if the array is a one-dimensional array, it can be considered a deep copy. If it is a multidimensional array, it is a shallow copy.

3. Array.slice ()

The slice method can return the selected element from an existing array.

var o1 = [1, [2], 3]var o2 = o1.slice(0)console.log(o1) // [1, [2], 3]console.log(o2) // [1, [2], 3]

Instead of modifying the array, the method returns a sub-array.

o1[0] = 11console.log(o1) // [11, [2], 3]console.log(o2) // [1, [2], 3]

As seen from the results, only the value of O1 was modified, and the value of O2 was not modified.

o1[1][0] = 22console.log(o1) // [11, [22], 3]console.log(o2) // [1, [22], 3]

The result shows that the values of the two variables of O1 and O2 have changed. Description, both references point to the same memory address.

Above, the description is a shallow copy.

4. Object.assign ()

The Object.assign () method is used to copy the values of all enumerable own properties from one or more source objects to the target object. It returns the target object

var o1 =  { a : 1, b : { c : 2, d : 3} }var o2 = Object.assign({}, o1)console.log(o1) // { a : 1, b : { c : 2, d : 3} }console.log(o2) // { a : 1, b : { c : 2, d : 3} }console.log(o2 === o1) // false    说明实现了浅拷贝o1.a = 11console.log(o2) // { a : 1, b : { c : 2, d : 3} }    o1和o2内部包含的基本类型值,拷贝的是其实例,不会相互影响o1.b.c = 22console.log(o1) // { a : 11, b : { c : 22, d : 3} }console.log(o2) // { a : 1, b : { c : 22, d : 3} }    o1和o2内部包含的引用类型值,拷贝的是其引用,会相互影响
5. Using the Extend function in jquery
// Shallow copyjQuery.extend({},OriginalObject)// Deep copy jQuery.extend(true, {},OriginalObject)

jQuery.extend( [deep ], target, object1 [, objectN ] ), where Deep is a Boolean type and, if true, deeply copied.

var $ = require('jquery')var o1 = { a : 1, b : { c : 2 } }var o2 = $.extend({}, o1)console.log(o1.b === o2.b) // trueconsole.log(o1.a === o1.a) // false
6. _.clone in Lodash ()

The use of structured copy algorithms. Support Copy Arrays,array Buffers,booleans, data objects, maps,

Numbers, Object objects, regexes, sets, strings, symbols, and typed
Arrays. An arguments enumerable property of an object is copied as a normal object.
Returns an empty object for non-copied values such as Error objects, functions, DOM nodes, and weak mappings.

Shallow copy:_.clone()

Deep copy:_.cloneDeep()

var objects = [{ 'a': 1 }, { 'b': 2 }]; var shallow = _.clone(objects);console.log(shallow[0] === objects[0]); // trueobjects[0].a = 11console.log(shallow[0]) // { a : 11}
Deepcopy deep Copy Implementation mode 1. Copy manually

To achieve a copy of the copy, not affected by the original, then you can do so

var o1 = { a : 1, b : 2 }var o2 = { a : o1.a, b : o1.b }console.log(o2 === o1) // falseo1.a = 2console.log(o1) // {a: 2, b: 2}console.log(o2) // {a: 1, b: 2}

A deep copy is implemented by copying values for each reference object.

2. Json.parse (Json.stringify (Object_array))
    • Json.stringify (): Converting an object to a string

    • Json.parse (): Converting a string to an object

var o1 = { a : 1, b : { c : 2} }var o2 = JSON.parse(JSON.stringify(o1))console.log(o1 === o2) // falseconsole.log(o1.b === o2.b) // falseo1.b.c = 22o1.a = 11console.log(o1) //   { a : 11, b : { c : 22} }console.log(o2) //   { a : 1, b : { c : 2} }

This way, only for types that can be converted to JSON objects, such as Array,object. If a function is encountered, it does not apply.

3. Meet the Jquery.extend () method again

jQuery.extend( [deep ], target, object1 [, objectN ] ), where Deep is a Boolean type and, if true, deeply copied.

Jquery.extend () source jquery.extend = JQuery.fn.extend = function () {var options, name, SRC, copy, Copyisarray, clone, target = arguments[0] | | {},//define variable, get first parameter.        The default is an empty object.     i = 1, length = arguments.length, deep = false;         Handle a deep copy situation handles the dark copy if (typeof target = = = "Boolean") {depth = target; Skip the Boolean and the target//skip Boolean and destination, re-assign target target = arguments[I] | |        {};    i++; }//Handle case if Target is a string or something (possible in depth copy)//When the target is a string or other (may be used in the deep copy) processing use cases/    /When the target is non-object and is not a function when handling if (typeof target!== "Object" &&!jquery.isfunction (target)) {target = {};        }//Extend jquery itself if only one argument is passed//if you only pass a parameter, extend jQuery itself if (i = = length) {        target = this;    i--; } for (; i < length; i++) {//* deal with non-null/undefined values//processing only non-null/undefined value        if (options = arguments[I] = null) {//Extend the Base Object//Expand base/Source Object                for (name in options) {src = target[name];                 copy = options[name];                 Prevent never-ending loop//Prevent infinite loop if (target = = = copy) {continue;                }//Recurse If we ' re merging plain objects or arrays//If you want to merge pure objects or arrays, use recursion if (deep && copy && jquery.isplainobject (copy) | | (Copyisarray = Array.isarray (copy)))                        {if (copyisarray) {Copyisarray = false; clone = src && array.isarray (src)?                     SRC: [];                    } else {clone = src && jquery.isplainobject (src)? src: {};                   }//Never move original objects, clone them Do not move the original object, copy them target[name] = Jquery.extend (deep, clone, copy);                    Don ' t bring in undefined values//do not introduce undefined value} else if (copy!== undefined) {                target[name] = copy; }}}}//Return the Modified object//return target after the modification;};
4. _.clonedeep in Lodash ()

Using the third-party library Lodash, its deep copy function Clonedeep (), this function is still relatively reliable, most of the requirements can be satisfied.

var o1 =  { a : 1, b : { c : 2} }var o2 = _.cloneDeep(o1)console.log(o1 === o2) // falseo1.a = 11o1.b.c = 22console.log(o1) // { a : 11, b : { c : 22} }console.log(o2) // { a : 1, b : { c : 2} }
5. Make a deep copy of yourself

For the complex types of array and object two, you implement a deep copy yourself. Self-fulfilling deep copy, compared to jquery's. Undefined and null values are not considered.

// 检测数据类型的函数function typeString(obj) {    var cons =   Object.prototype.toString.call(obj).slice(8, -1)     return (cons === 'Array' || cons === 'Object')}// 实现深度拷贝 Array/Objectfunction deepClone(oldObj) {    if(typeTrue(oldObj)) {        var newObj = oldObj.constructor()        for(let i in oldObj) {            if (oldObj.hasOwnProperty(i)) {                newObj[i] = typeTrue(oldObj[i]) ? deepClone(oldObj[i]) : oldObj[i]            }        }  return newObj;    } else {        return oldObj    }}// 测试var o1 = [1, 2, [3, 4]]var o2 = deepClone(o1)console.log(o1 === o2) // falseo1[2][0] = 2018console.log(o2) // [1, 2, [3, 4]]console.log(o1) // [1, 2, [2018, 4]]
Depth Copy Summary

It is an important indicator that the copy will affect each other. The depth copies discussed above are small in scope, most of which only consider object and array types, but can be used in most cases.
Function, Data, regexp, etc. are not considered. If you need to consider these, can be specific to specific situations, such as Lodash _.clone, is the use of structured copy algorithm, for different situations to copy.

Shallow copy shallowcopy and deep copy deepcopy in JavaScript

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.