Shallow copy and deep copy of js

shallow copy

var m = { a: 10, b: 20 }
var n = m;
na = 15; // What is the value of ma at this time?
ma will output 15, because this is a shallow copy, and n and m point to the same heap , the object copy is just a reference to the copied object.

deep copy

var m = { a: 10, b: 20 }
var n = {a:ma,b:mb};
na = 15;
Deep copy is different from the above shallow copy, it is to completely copy an object, not copy the reference of the object.
This time, we output ma again, and found that the value of ma is still 10, which has not changed. Although all the values ​​of the m object and the n object are the same, but in the heap, they correspond to different ones. This is a deep copy .

deep copy and shallow copy

The schematic diagram of deep copy and shallow copy is roughly as follows:

image.png

Shallow copy only copies the pointer to an object, not the object itself, and the old and new objects still share the same memory. However, deep copy will create an identical object. The new object does not share memory with the original object, and modifying the new object will not change the original object.

The implementation of shallow copy


1. It can be realized by simple assignment

    var obj = {}; 
    for ( var i in initalObj) { 
        obj[i] = initalObj[i]; 
    } 
    return obj; 
} 
var obj = { 
    a: "hello", 
    b:{ a: "world", b: 21 }, 
    c:["Bob", "Tom", "Jenny"], 
    d:function() { 
        alert("hello world"); 
    } 
} 
var cloneObj = simpleClone(obj); 
console.log(cloneObj.b); 
console.log(cloneObj.c); 
console.log(cloneObj.d); 
cloneObj.b.a = "changed"; 
cloneObj.c = [1, 2, 3]; 
cloneObj.d = function() { 
    alert("changed"); 
}; 
console.log(obj.b); 
console.log(obj.c); 
console.log(obj.d);

2. Implementation of Object.assign()

The Object.assign() method can copy any number of enumerable properties of the source object itself to the target object, and then return the target object. But Object.assign() performs a shallow copy, which copies the references to the properties of the object, not the object itself.

var initalObj = Object.assign({}, obj);
initalObj.a.a = "changed";
console.log(obj.a.a); //  "changed"

Note: When the object has only one layer, it is a deep copy, for example as follows:

var obj2 = Object.assign({}, obj1);
obj2.b = 100;
console.log(obj1);
// { a: 10, b: 20, c: 30 } <-- 沒被改到
console.log(obj2);
// { a: 10, b: 100, c: 30 }

3. The _.clone method of the function library lodash

The function library also provides _.clone for Shallow Copy, and we will introduce the use of this library to implement deep copy later.

var obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
var obj2 = _.clone(obj1);
console.log(obj1.b.f === obj2.b.f);// true

4. Spread operator...

The spread operator is an es6/es2015 feature that provides a very convenient way to perform shallow copies, the same functionality as Object.assign().

let obj2= {... obj1}
obj1.address.x = 200;
obj1.name = 'wade'
console.log('obj2',obj2) // obj2 { name: 'Kobe', address: { x: 200, y: 100 } }

5、Array.prototype.concat()

    username: 'kobe'
    }];
let arr2 = arr.concat();    
arr2[2].username = 'wade';
console.log(arr); //[ 1, 3, { username: 'wade' } ]

6、Array.prototype.slice()

let arr = [1, 3, {
    username: ' kobe'
    }];
let arr3 = arr.slice();
arr3[2].username = 'wade'
console.log(arr); // [ 1, 3, { username: 'wade' } ]

Implementation of deep copy


1. The first method is to manually copy

Like the above example, manual copying can achieve deep copying.

2. If the object has only one layer, you can use the above: Object.assign() function

3. Convert to JSON and back

var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.body.a = 20;
console.log(obj1);
// { body: { a: 10 } } <-- 沒被改到
console.log(obj2);
// { body: { a: 20 } }
console.log(obj1 === obj2);
// false
console.log(obj1.body === obj2.body);
// false

Use JSON.stringify to convert the object into a string, and then use JSON.parse to convert the string into a new object.

4. The _.cloneDeep method of the function library lodash

The function library also provides _.cloneDeep for Deep Copy

var _ = require('lodash');
var obj1 = { a: 1, b: { f: { g: 1 } }, c: [1, 2, 3] }; var obj2 = _.cloneDeep(obj1) ; console.log(obj1.bf === obj2.bf);// false 5. Recursive copy






function deepClone(initalObj, finalObj) {    
  var obj = finalObj || {};    
  for (var i in initalObj) {        
    var prop = initalObj[i];        // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
    if(prop === obj) {            
      continue;
    }        
    if (typeof prop === 'object') {
      obj[i] = (prop.constructor === Array) ? [] : {};            
      arguments.callee(prop, obj[i]);
    } else {
      obj[i] = prop;
    }
  }    
  return obj;
}
var str = {};
var obj = { a: {a: "hello", b: 21} };
deepClone(obj, str);
console.log(str.a);

6. Use the Object.create() method

Directly use var newObj = Object.create(oldObj) to achieve the effect of deep copy.

function deepClone(initalObj, finalObj) {    
  var obj = finalObj || {};    
  for (var i in initalObj) {        
    var prop = initalObj[i];        // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
    if(prop === obj) {            
      continue;
    }        
    if (typeof prop === 'object') {
      obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
    } else {
      obj[i] = prop;
    }
  }    
  return obj;
}

7、jquery

jquery provides a $.extend that can be used for Deep Copy.

var $ = require('jquery');
var obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
var obj2 = $.extend(true, {}, obj1);
console.log(obj1.b.f === obj2.b.f);
// false

8、lodash

Another very popular function library, lodash, also provides _.cloneDeep for Deep Copy.

var _ = require('lodash');
var obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
var obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);
// false

Guess you like

Origin blog.csdn.net/DragonOfMoon/article/details/124072778