当前位置:网站首页>123. deep and shallow copy of JS implementation -- code text explanation

123. deep and shallow copy of JS implementation -- code text explanation

2022-06-21 09:18:00 @Upwind smile code dog

js Realize deep and shallow copy

1. Concept ;

Shallow copy : When assigning values to objects , New object after assignment , If you change the value of the first level , that After the assignment New object The corresponding value is also Meeting Change with it , This is a shallow copy of the object , Also known as Shallow copy

Deep copy : When assigning values to objects , New object after assignment , If you change the value of the second level or other levels after the second level , that After the assignment New object The corresponding value is also Can't Change with it , This is a deep copy of the object , Also known as Deep copy

The case is as follows :

let  obj = {
	a: 100,
	b: 200
}
let newObj = obj
obj.a = 100
console.log(obj)  // { a: 200, b: 200 } 
console.log(newObj) // { a: 200, b: 200 }

From the above cases, it can be found that , The assigned object newObj Will follow Old object obj Changes with the value of

2. The reason for the shallow copy ?

because obj Is the reference data type , The reference data type exists in Heap memory in , The memory in the heap space will be Stack memory The reference address in , and Copy of object The copy actually exists in Stack memory The reference address in , And that leads to this Two reference addresses Point to the same Heap memory Space , If you change one of the memory reference addresses , Then the data in the same heap space will be modified , This leads to data confusion , That is, the problem caused by shallow copy

3. Solution : Make an assignment to the data of the object

Solve this problem Of There are many plans , I started from es 3 To es6 All the plans are sorted out

es3

Define an empty object , adopt fon in loop Make a copy of the old data

let obj = { a:100, b:200 }
function es3Copy(obj){
	let newObj = {}
     for (const key in obj) {
          newObj[key] = obj[key]
     } 
     return newObj
}
let es3 = es3Copy(obj)
obj.a = 101
console.log(obj) // { a:101, b:200 }
console.log(es3) // { a:100, b:200 }

es5

adopt Object.defineProperty() The way

  • getOwnPropertyNames( object ) Returns the name of the specified object key
  • getOwnPropertyDescriptor(obj, v) return Appoint key Of Describe objects
    • configurable: true // Configurable
    • enumerable: true // Enumerable or not
    • value: 1 // The key Corresponding value
    • writable: true // Is it possible Reading and writing
let obj = { a:100, b:200 }
function es5Copy(obj){
    let newObj = {}
    Object.getOwnPropertyNames(obj).forEach( v => {
        let des = Object.getOwnPropertyDescriptor(obj, v)
        Object.defineProperty(newObj, v, des)
    })
    return newObj
}
let es5 = es3Copy(obj)
obj.a = 101
console.log(obj) // { a:101, b:200 }
console.log(es5) // { a:100, b:200 }

es6

let obj = { a:100, b:200 }
function es6Copy(obj){
	let newObj = {}
    // console.log(Object.keys(obj));
    // console.log(Object.values(obj));
    // console.log(Object.entries(obj))
    
   for (const [key, value] of Object.entries(obj)) {
   		newObj[key] = value
   } 
   return newObj
}
let es6 = es6Copy(obj)
obj.a = 101
console.log(obj) // { a:101, b:200 }
console.log(es6) // { a:100, b:200 }

This sentence needs to be rigorous :javaScript Storage objects are stored in addresses , So shallow copies can lead to obj1 and obj2 Point to the same memory address . Changed the content of one party , All modifications are made in the original memory, which will lead to changes in both the copy object and the source object , Deep copy is to open up a new memory address , Copy the attributes of the original object one by one . The operations of the copy object and the source object do not affect each other .

4. Deep copy

Mode one : recursive

Using recursion , Copy layer by layer

let obj = {
    a: 1,
    b: 2,
    c: {
        d: {
            e: 100
        }
    }
}

function deepCopy(obj){
	let newObj = Array.isArray(obj) ? [] : {}
	if( obj && typeof newObj ==='object' ){
		for(const key in obj){
			if( typeof obj[key] === 'object' ){
				newObj[key] = deepCopy(obj[key])
			}else{
				newObj[key] = obj[key]
			}
		}
	}else{
	  return ' Please pass in the correct data type '
	}
	return newObj
}
let res = deepCopy(obj)
obj.c.d.e = 200
console.log(obj) 
console.log(res)
Mode two :API

JSON.parse(JSON.stringify(obj)) serialize and Deserialization

let obj = {
    a: 1,
    b: 2,
    c: {
        d: {
            e: 100
        }
    }
}
let newObj = JSON.parse(JSON.stringify(obj))  
obj.c.d.e = 200
console.log(obj)
console.log(newObj)
JSON.parse() The disadvantages of

We are using JSON.parse(JSON.stringify(xxx)) We should pay attention to a few points when :

1、 If obj There are time objects in it , be JSON.stringify Later JSON.parse Result , Time will just be in the form of a string . Not the time object
var test = {
     name: 'a',
     date: [new Date(1536627600000), new Date(1540047600000)],
   };

   let b;
   b = JSON.parse(JSON.stringify(test))
2. If obj Are there in RegExpError object , The result of serialization will only get empty objects ;
const test = {
     name: 'a',
     date: new RegExp('\\w+'),
   };
   // debugger
   const copyed = JSON.parse(JSON.stringify(test));
   test.name = 'test'
   console.error('ddd', test, copyed)
3、 If obj There are functions ,undefined, The result of the serialization will be the function or undefined The loss of ;
const test = {
        name: 'a',
        date: function hehe() {
          console.log('fff')
        },
      };
      // debugger
      const copyed = JSON.parse(JSON.stringify(test));
      test.name = 'test'
      console.error('ddd', test, copyed)
4. If obj Are there in NaN、Infinity and -Infinity, The result of serialization will be null
5.JSON.stringify() Only enumerable properties of an object can be serialized , for example If obj Objects in are generated by constructors , Then use JSON.parse(JSON.stringify(obj)) After deep copy , Will discard the object constructor;
function Person(name) {
	  this.name = name;
	  console.log(name)
	}
	
	const liai = new Person('liai');
	
	const test = {
	  name: 'a',
	  date: liai,
	};
	// debugger
	const copyed = JSON.parse(JSON.stringify(test));
	test.name = 'test'
	console.error('ddd', test, copyed)
6、 If there are circular references in the object, deep copy cannot be implemented correctly ;
原网站

版权声明
本文为[@Upwind smile code dog]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202221445473036.html