Jun 01, 2021 Article blog
"Copy" has always been a hot topic for interviews. S eemingly simple, but it is difficult to live a lot of interviewers, the answer sloppy, ambiguous. Take the time to analyze and summarize the "copy" and let the puzzle disappear completely.
From a story, yesterday because the hospital can not open medicine, I took medicine to take the community pharmacy to buy medicine, after entering the door I asked the boss whether there is this medicine, the boss turned into a small room to take a box of medicine, it is true, the name of the medicine and milligram touch the same, but the appearance of the box and manufacturers are not the same, I asked the boss: "These two drugs are a medicine, the box is not the same ah, the ingredients of the drug is the same?" " The boss said of course, this is the same as you go to buy pork, the same as pig meat, but you go to this supermarket and go to other supermarkets to buy the same place." Finally, I didn't buy the medicine for safety reasons.
Copy is divided into shallow and deep copies. I
t is for
对象
if not objects. T
he object here can be understood as the box of medicine I took,
浅拷贝
can be understood as the box taken by the boss, although the name of the medicine is the same as milligrams, and then inside we do not know whether it is really the same, may be the same may not be the same.
深拷贝
can be understood for me to buy a touch of the same medicine, layer by layer of drug name, milligrams, manufacturers, ingredients are the same.
summary:
引用
problem that is, the memory address refers to the same address.
Simply put, after copying, it's
有关
the original object.
无关
Here's an example of a shallow copy:
let school={'name':"W3Cschool"};
let my = {age:{count:18},name:"W3Cschool编程狮"};
let all = {...school,...my};
my.age.count=100;
console.log(all);
console.log(my);
outcome:
{ age: { count: 100 }, name: 'W3Cschool编程狮' }
{ age: { count: 100 }, name: 'W3Cschool编程狮' }
The conclusion is that the properties on the object after the shallow copy is modified will modify the properties on the original object at the same time.
Here's another example of a deep copy:
const _ = require("loadsh")
let my = {age:{count:18},name:"W3Cschool编程狮"};
let all = _.cloneDeep(my);
all.age.count =100;
console.log(my);
console.log(all);
outcome:
{ age: { count: 18 }, name: 'W3Cschool编程狮' }
{ age: { count: 100 }, name: 'W3Cschool编程狮' }
The conclusion is that the properties on the object after the deep copy is modified do not modify the properties on the original object at the same time.
1. Array methods: slice and concat
let arr = [1,2,3,4];
let arr2 = arr.slice(0)
arr2[2]=5;
console.log(arr); //[ 1, 2, 3, 4 ]
console.log(arr2); //[ 1, 2, 5, 4 ]
When the array is not an object, it is a deep copy from the result, in the following example
let arr = [{1:1,2:2}];
let arr2 = arr.slice(0)
arr2[2]=5;
console.log(arr); //[ { '1': 1 }, { '2': 5 } ]
console.log(arr2); //[ { '1': 1 }, { '2': 5 } ]
When an object is in an array, it becomes a shallow copy
let arr = [1,2,3,4];
let arr2 = [].concat(arr);
arr2[2]=5;
console.log(arr); //[ 1, 2, 3, 4 ] ✔
console.log(arr2); //[ 1, 2, 5, 4 ]
When the array is not an object, it is a deep copy from the result, in the following example
let arr = [{1:1},{2:2}];
let arr2 = arr.cancat(0)
arr2[1][2]=5;
console.log(arr); //[ { '1': 1 }, { '2': 5 } ] ❌变成了引用
console.log(arr2); //[ { '1': 1 }, { '2': 5 } ]
When an object is in an array, it becomes a shallow copy
Summary: Deep copy is only once the array is a one-dimensional array and does not contain objects
(Recommended tutorial: JavaScript tutorial)
2. Object.assgin()
let a= {a:1,b:2};
let b= Object.assign({},a);
a.a=3;
console.log(a) //{a: 3, b: 2}
console.log(b) //{a: 1, b: 2} ✔
let a= {a:1,b:{c:2}};
let b= Object.assign({},a);
a.b.c=3;
console.log(a) //{a: 1, b: {c:3}}
console.log(b) //{a: 1, b: {c:3}} ❌变成了引用
Summary: Object.assgin becomes a reference solution when it comes to nesting multiple objects: use
JSON.stringify()
to convert to a string and then through
JSON.parse()
to an object
let a= {a:1,b:{c:2}};
let b= JSON.parse(JSON.stringify(a))
a.b.c=3;
console.log(a) //{a: 1, b: {c:3}}
console.log(b) //{a: 1, b: {c:2}} ✔
let school={'name':"W3Cschool编程狮",fn:function(){}};
let my = {age:{count:18},name:"W3Cschool编程狮"};
let all=JSON.parse(JSON.stringify({...school,...my}))
console.log(all); //{'name':"W3Cschool编程狮",age:{count:18}}; //❌把fn给丢了
Summary: JSON.parse (JSON.stringify() has some limitations and loses fn.
let deepClone=(obj)=>{
if(obj==undefined) return obj; //undefined == null
if(obj instanceof RegExp) return new RegExp(obj);
if(obj instanceof Date) return new Date(obj);
if(typeof obj!=="object") return obj;
let newObj = new obj.constructor;
for(let key in obj){
if(obj.hasOwnProperty(key)){
newObj[key] = deepClone(obj[key])
}
}
return newObj;
}
let obj1 = {name:{age:"10"}}
let n = deepClone(obj1)
obj1.name.age = "231"
console.log(n); //{name:{age:"10"}} ✔
let obj = { name:"W3Cschool编程狮" }
obj.aaa=obj
let n = deepClone(obj1)
console.log(n); //死循环了 ❌
You can use WeakMap to solve this problem
let deepClone=(obj,hash=new WeakMap())=>{
if(obj==undefined) return obj; //undefined == null
if(obj instanceof RegExp) return new RegExp(obj);
if(obj instanceof Date) return new Date(obj);
if(typeof obj!=="object") return obj;
if(hash.has(obj)) return hash.get(obj);
let newObj = new obj.constructor;
hash.set(obj,newObj);
for(let key in obj){
if(obj.hasOwnProperty(key)){
newObj[key] = deepClone(obj[key],hash)
}
}
return newObj;
}
源码地址:https://github.com/lodash/lodash/blob/86a852fe763935bb64c12589df5391fd7d3bb14d/.internal/baseClone.js
function clone (value) {
if (Array.isArray(value)) {
return value.map(clone)
} else if (value && typeof value === 'object') {
const res = {}
for (const key in value) {
res[key] = clone(value[key])
}
return res
} else {
return value
}
}
let arr = [{1:1},{2:2},function(){}];
let arr2 = clone(arr)
arr2[1][2]=5;
console.log(arr) //[ { '1': 1 }, { '2': 2 }, [Function (anonymous)] ] ✔ 深拷贝
console.log(arr2); //[ { '1': 1 }, { '2': 5 }, [Function (anonymous)] ]
function extend (a, b) {
for (const key in b) {
a[key] = b[key]
}
return a
}
let b={a:1,b:{c:2}};
let a= extend({},b);
a.b.c=5;
console.log(a); //{ a: 1, b: { c: 5 } }
console.log(b); //{ a: 1, b: { c: 5 } } 浅拷贝
(Recommended micro-class: JavaScript micro-course)
Source: Public Number - Clown's Cabin Author: Clown
That's what
W3Cschool编程狮
has to say about the perfect solution to JavaScript's deep copy, and I hope it will help you.