Reasons for shallow and deep copies

Because when the object is assigned, it copies the address value, so one side changes and the others change.

Shallow copy is designed to solve this problem.

let a = {age: 22}; let b = a; a.age = 11; console.log(b.age); / / 11Copy the code

Shallow copy method:

Method 1: Object.assign()

  • Object shallow copy
let a = {age:22} let b = Object.assign({},a); a.age = 11; console.log(b.age); / / 22Copy the code

Method 2: three-point operator

  • Object and array copy
let a = {age: 22}; let b = { ... a }; a.age = 11; console.log(b.age) //22Copy the code

Method 3: concat/slice

  • Copy an array
Let a = [1,2,3] let b = a.c ();Copy the code
Let a = [1,2,3] let b = a.ice (0);Copy the code

Method 4: For-in

function clone (val) {
    let newVal = Array.isArray(val) ? [] : {};
    for(var i in val){newVal[i] = val[i]};
    return newVal;
};
Copy the code

Shallow copy problems:

  • The problem is that the problem can only be solved at the first level, not if the second level is objects. So you need to use deep copy
let a = {age: 22, jobs:{name: 'FF'}};
let b = Object.assign({},a);
a.jobs.name = 'FE';
console.log(b.jobs.name) //FE
Copy the code

Deep copy

Method 1: JSON serialization (error: missing undefined, Symbol, function, object)

let obj = { a: 1, b: 'str', c: undefined, e: Symbol('e'), f: function(){console.log('f')}, g: {a: 1}, } let newObj = JSON.parse(JSON.stringify(obj)); //{a: 1, b: "str"} obj.g.a = 2; console.log(newObj.g.a) //1 let obj = { a: 1, b: 'str', g: {a: 1}, } obj.c = obj.g; obj.g.b = obj.c; let newObj = JSON.parse(JSON.stringify(obj)); // An error was reported, the object could not be referenced circularlyCopy the code

Method 2: If you don’t have symbols and functions, use the MessageChannel method for deep copy.

// MessageChannel is asynchronous; const cloneDeep = (o) => { return new Promise(resolve=>{ const {port1,port2} = new MessageChannel(); port1.onmessage = ()=>resolve(o) port2.postMessage(o); })}; Const obj = {a: 1, b: 'STR' c: undefined, / / d: function () {the console. The log (' d ')}, function, an e: {a: 'a'}}; obj.g = obj.e; obj.e.a=obj.g; const test = async() => { const newObj = await cloneDeep(obj); console.log(newObj); }; test(); // Circular references are also fineCopy the code

Method 3: Write your own deep copy

  • There’s a lot of boundary issues to think about, DOM, prototype chains, things like that. So using lodash’s deep copy is recommended.
function deepClone (obj) { const isObject = (o) => { return (typeof o === 'object') && o ! == null }; if(! isObject(obj)){return obj}; let newObj = Array.isArray(obj) ? [...obj] : {... obj}; Reflect.ownKeys(newObj).forEach(key=>{ newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]; }); return newObj; } const objTest = {a: [1,2,3], b: {a:'a',b:'b'}} const newO = deepClone(objTest); objTest.b.a = 1; Console. log(newo.b.a) // Determines whether the attribute value is an object. If so, it is recursiveCopy the code