preface
The Javascript world divides data types into two types: raw data types and reference data types.
There are eight data types: String, Number, Boolean, Null, Undefined, Object, Symbol(ES6), Bigint(ES10).
- Raw data type:
String
,Number
,Boolean
,Null
,Undefined
,Symbol
,Bigint
. - Reference data types:
Object
(Array, Function, Date, RegExp, etc.).
Different types of storage:
- Raw data type: The value of the raw data type occupies a fixed size in memory and is stored in stack memory.
- Reference data type: The value of a reference data type is an object, which in stack memory only holds the variable identifier of the object and the storage address of the object in heap memory. Its contents are stored in the saved heap memory.
Different types of copy modes:
-
Primitive data type
In the case of raw data types, copying from one variable to another is a very simple assignment process that doesn’t matter.
let a = 1; let b = a; a = 3; console.log(a, b); / 1/3Copy the code
-
Reference data type
For reference data types, copying from one variable to another essentially copies the storage address of the object, and both variables end up referring to the same object.
Let a = {name: 'orange '}; let b = a; a.name = 'yd'; console.log(a, b); let c = [1]; let d = c; c[0] = 2; console.log(c, d);Copy the code
So in this chapter we’ll talk about shallow and deep copying for reference data types, so let’s take a closer look.
Shallow copy and deep copy
concept
Why do shallow and deep copies exist? A simple sentence: “Prevent parent object data from being tampered with.”
- Shallow copy: After a copy is complete, operations may affect each other.
- Deep copy: After a copy is complete, operations on each other will not affect each other.
Shallow copy
- Array shallow copy –
concat()
,slice()
let arr = [1, 2, 3];
let newArr = arr.concat();
newArr[0] = 20;
console.log(arr, newArr); // [1, 2, 3] [20, 2, 3]
let arr1 = [1, 2, 3];
let newArr1 = arr1.slice();
newArr1[0] = 20;
console.log(arr1, newArr1); // [1, 2, 3] [20, 2, 3]
Copy the code
- Object shallow copy
function copy(object) { let o = {}; for(let key in object) { o[key] = object[key]; } return o; } let obj = {name: 'obj '}; let newObj = copy(obj); newObj.name = 'YD'; console.log(obj, newObj); // {name: "orange "} {name: "YD"}Copy the code
Meng? Doesn’t it say that what doesn’t interact is deep copy? Xiaobian cheating you? How will? Don’t worry.
I’m keeping an eye on the fact that shallow copies may interact with each other, which means that shallow copies may not interact.
Word games? Xiaobian play a word game? Call me…
If the object has only one level of depth and is only a common primitive data type value, then you say that the above example is a deep copy, then I do not refute, haha.
However, they are shallow copies, if the object depth is below multiple layers, it will not escape.
// array let arr = [1, 2, [1]]; let newArr = arr.concat(); newArr[2][0] = 10; console.log(arr, newArr); // [1, 2, [10]] [1, 2, [10]] let arr1 = [1, 2, [1]]; let newArr1 = arr1.slice(); newArr1[2][0] = 10; console.log(arr1, newArr1); / / [1, 2, [10]] of [1, 2, [10]] / / object function copy (object) {let o = {}; for(let key in object) { o[key] = object[key]; } return o; } let obj = {name: 'obj ', hobby: {val: 'basketball'}}; let newObj = copy(obj); newObj.hobby.val = 'football'; console.log(obj, newObj); / / {name: 'orange someone' hobby: {val: 'football'}} {name: 'orange someone' hobby: {val: 'football'}}Copy the code
Multi-level shallow copies of objects cannot be handled, in which case deep copies are required.
Deep copy
The deep copy does not simply copy the reference address, but reallocate the memory in the heap, and make a new copy of all the attributes of the source object, to ensure that the object reference of the deep copy does not contain any original object or any object attributes on the object, and the copied object is completely isolated from the original object.
JSON.parse()
,JSON.stringify()
- Array deep copy –
JSON.parse()
,JSON.stringify()
let arr = [1, 2, [1]];
let newArr = JSON.parse(JSON.stringify(arr));
newArr[2][0] = 10;
console.log(arr, newArr); // [1, 2, [1]] [1, 2, [10]]
let arr1 = [1, 2, [1]];
let newArr1 = JSON.parse(JSON.stringify(arr1));
newArr1[2][0] = 10;
console.log(arr1, newArr1); // [1, 2, [1]] [1, 2, [10]]
Copy the code
- Object deep copy –
JSON.parse()
,JSON.stringify()
Let obj = {name: 'orange ', hobby: {val: 'basketball'}}; let newObj = JSON.parse(JSON.stringify(obj)); newObj.hobby.val = 'football'; console.log(obj, newObj); // {name: "yd", hobby: {val: 'basketball'}} {name: "yd", hobby: {val: 'football'}}Copy the code
Parse (), json.stringify () is too simple to use? Haha, but. Simplicity certainly has its drawbacks, such as:
let arr = [() => {}, { b: () => {} }, new Date()];
let newArr = JSON.parse(JSON.stringify(arr));
console.log(newArr);
let obj = {a: () => {}, b: new Date()};
let newObj = JSON.parse(JSON.stringify(obj));
console.log(newObj);
Copy the code
Terrible not? The function is gone, right? Date type to string? This is the downside, it has to be said and used with caution.
recursive
Although above means is more simple and convenient, but when using, still want to think a little, save to be pit.
Below we use recursion to realize the deep copy, which idea: in the property of the value of the copy when we first judge the type of it, if it is an object, we recursively call the deep copy function, if not directly copy the past, how simple.
Function deepCopy(obj) {if (typeof obj! == 'object') return; let result = obj instanceof Array ? [] : {}; for (let key in obj) { if (obj.hasOwnProperty(key)) { result[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key]; } } return result; }Copy the code
Test the code.
// array let arr = [1, 2, [1]]; let newArr = deepCopy(arr); newArr[2][0] = 10; console.log(arr, newArr); // [1, 2, [1]] [1, 2, [10]] let arr1 = [1, 2, [1]]; let newArr1 = deepCopy(arr1); newArr1[2][0] = 10; console.log(arr1, newArr1); / / [1, 2, [1]] of [1, 2, [10]] / / object obj = {name: 'yd, hobby: {val:' also '}}; let newObj = deepCopy(obj); newObj.hobby.val = 'football'; console.log(obj, newObj); // {name: "yd", hobby: {val: 'basketball'}} {name: "yd", hobby: {val: 'football'}}Copy the code
Then let’s test the special functions and date types.
let arr = [() => {}, { b: () => {} }, new Date()];
let newArr = deepCopy(arr);
console.log(newArr);
let obj = {a: () => {}, b: new Date()};
let newObj = deepCopy(obj);
console.log(newObj);
Copy the code
According to the figure above, we can see that the function is fine, or it is preserved, but the date is dead, and the object is empty. Why? Do not worry, the deepCopy function deepCopy() problem, we will change.
function deepCopy(obj) { if (typeof obj ! == 'object') return; let result = obj instanceof Array ? [] : {}; for (let key in obj) { if (obj.hasOwnProperty(key)) { result[key] = typeof obj[key] === 'object' && ! (obj[key] instanceof Date) ? deepCopy(obj[key]) : obj[key]; } } return result; }Copy the code
This is normal now, okay? Hey hey ~ do not understand their own enlightenment, this chapter is almost like this, bye bye. (Of course, recursion is only one way, the Internet search for a variety of ways to achieve deep copy, absolutely elegant, interested can slowly study.)