Welcome to pay attention to my public number
The Code of Life
Interviewer: Always ask me the depth of the copy questions, read the article
If you go out for an interview, the interviewer will always ask you some amazing questions, but you have to know, today’s question is one of them, in our work, actually we often use object copy, array copy, but often ignore the principle of it, today we will explore.
Look at the beginning of this article with two questions in mind:
- What is light copy
- How to implement shallow copy
What is light copy
With the help of ConardLi’s following two pictures, help us better understand the meaning of both:
From the above two pictures, we can know:
Shallow copy: For example, we define a variable asobj
And then we assign it to another variable. This process involves shallow copy problems. The other variable is just a copy of the previous variable, and the storage address of the two variables is the same. You can think of assignment as actually binding addresses together
There are two caveats:
- Reference data types: objects, arrays, functions, etc. These copy addresses
let obj = {name: {code: 'Life Code'}}
let copyObj = obj
console.log(copyObj.name === obj.name) // true indicates that the same reference address is used
Copy the code
- Basic data types: numbers, strings, booleans these are copy values
let str = "Ken"
let str1 = str
console.log(str === str1) // true but only copies the value
Copy the code
Deep copy
For example, we put our clothes in one closet, and then you buy the same clothes, and then you buy another closet for the new clothes, so that the two clothes are completely irrelevant.
Deep copy actually means this:
To make a complete copy of an object out of memory, a new area of heap memory is created to hold the new object, and modification of the new object does not affect the original object.
let obj = {name: {code: 'Life Code'}}
let copyObj = JSON.parse(JSON.stringify(obj))
console.log(copyObj.name === obj.name) // false indicates that the reference address is different
Copy the code
The difference between assignment and deep/shallow copy
We are comparing here with reference types:
The assignment
Assignment actually assigns the address of the object, the reference address of the array, which means that the two objects are linked, there is a relationship, whenever one variable changes, the other variable changes.
let obj = {
name: 'Life Code'.
arr: [1.2.3]
}
let obj1 = obj
obj1.name = "Ken"
obj1.arr = [4.5.6]
console.log(obj1, obj) / / obj1: {name: 'Ken, arr: [4 and 6]} obj: {name:' Ken, arr: (4 and 6)}
Copy the code
Shallow copy
When memory is created in the heap again, the basic data types of objects before and after the copy do not affect each other, but the reference types of objects before and after the copy do affect each other because they share the same memory block.
/ / shallow copy
let obj1 = {
name : 'Life Code'.
arr : [1.2.3].
};
let obj2=shallowClone(obj1)
obj2.name = "Ken";
obj2.arr = [5.6.7];// Old and new objects still share the same memory
// This is a shallow-copy method
function shallowClone(source) {
var target = {};
for(var i in source) {
if (source.hasOwnProperty(i)) {
target[i] = source[i];
}
}
return target;
}
console.log('obj1',obj1)
Obj1 {name: 'lifecode ', arr: [5,6,7]}
console.log('obj2',obj2)
// obj2 { name: 'Ken', arr: [ 5, 6, 7 ] }
Copy the code
Deep copy
Create a new area of heap memory to store the new object, and make a recursive copy of the child objects in the object. The two objects before and after the copy do not affect each other.
/ / copy
let obj1 = {
name : 'Life Code'.
arr : [1.2.3].
};
let obj2=deepClone(obj1)
obj2.name = "Ken";
obj2.arr = [5.6.7];// The new object does not share memory with the original object
// This is a deep-copy method
function deepClone(obj) {
if (obj === null) return obj;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
if (typeofobj ! = ="object") return obj;
let cloneObj = new obj.constructor();
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// Implement a recursive copy
cloneObj[key] = deepClone(obj[key]);
}
}
return cloneObj;
}
console.log('obj1',obj1)
Obj1 {name: 'lifecode ', arr: [1, 2, 3]}
console.log('obj2',obj2)
// obj2 { name: 'Ken', arr: [ 5, 6, 7 ] }
Copy the code
Shallow copy implementation
Object.assign()
let obj1 = { person: {name: "kobe".age: 41},sports:'basketball' };
let obj2 = Object.assign({}, obj1);
obj2.person.name = "wade";
obj2.sports = 'football'
console.log(obj1);
// { person: { name: 'wade', age: 41 }, sports: 'basketball' }
Copy the code
The _.clone method of the lodash library
var _ = require('lodash');
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
Copy the code
Expansion operator…
let obj1 = { name: 'Kobe'.address: {x:100.y:100}}
let obj2= {... obj1}
obj1.address.x = 200;
obj1.name = 'wade'
console.log('obj2',obj2)
// obj2 { name: 'Kobe', address: { x: 200, y: 100 } }
Copy the code
Array.prototype.concat()
let arr = [1.3, {
username: 'kobe'
}];
let arr2 = arr.concat();
arr2[2].username = 'wade';
console.log(arr);
//[ 1, 3, { username: 'wade' } ]
Copy the code
Array.prototype.slice()
let arr = [1.3, {
username: ' kobe'
}];
let arr3 = arr.slice();
arr3[2].username = 'wade'
console.log(arr);
// [ 1, 3, { username: 'wade' } ]
Copy the code
Deep copy implementation
JSON.parse(JSON.stringify())
The _. CloneDeep method of the lodash library
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
Copy the code
JQuery. The extend () method
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
Copy the code
Handwritten recursive method
The recursive method implements the principle of deep cloning: iterating through objects and arrays until they contain all the basic data types, and then copying, which is called deep copy.
There is a special case needs to pay attention to is the condition of the circular reference object, the object’s properties directly refer to its own situation, solve the problem of circular reference, we can open up a extra storage space, to store the current objects and copy the object correspondence, when need to copy the current object, go to the storage space, find ever copy this object, Return if there is, continue to copy if there is not, so as to cleverly solve the problem of circular reference. If in doubt about this, please read carefully how ConardLi can write a deep copy to impress the interviewer. This article.
function deepClone(obj, hash = new WeakMap()) {
if (obj === null) return obj;
// If it is null or undefined, I will not copy it
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
// May be objects or ordinary values if functions do not need deep copies
if (typeofobj ! = ="object") return obj;
// Make a deep copy of an object
if (hash.get(obj)) return hash.get(obj);
let cloneObj = new obj.constructor();
// Find the constructor from the parent class stereotype, which points to the current class itself
hash.set(obj, cloneObj);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// Implement a recursive copy
cloneObj[key] = deepClone(obj[key], hash);
}
}
return cloneObj;
}
let obj = { name: 1.address: { x: 100}};
obj.o = obj; // The object has a circular reference
let d = deepClone(obj);
obj.address.x = 200;
console.log(d);
Copy the code
reference
An article makes a deep and shallow copy of JavaScript
Copy the code