This is the 9th day of my participation in the August More Text Challenge
When coding in JavaScript, we often encounter situations where we need to copy objects or arrays, but sometimes it doesn’t work as expected. Let’s take a look!
Various types of data copying
Let’s start with an example
Copy number
You can see that all the results are normal
Copy string
You can see that the results are all normal
Copying arrays (wrong version)
We can see the following example
Expectations are
- Make a copy of the list to Box
- [1,2,3,’a’]
- [1,2,3,4,’b’]
The actual effect is
- When you change the list, the box is also changed
- When you change box, you change list
Copy object (wrong version)
We can see from the following example
-
Object A only changed the blog, should get
{ blog:'0', author:'Axjy' } Copy the code
-
Object B only changes author, should get
{
blog:'jueJin',
author:'1'
}
Copy the code
But you can see the end result, it’s all changed
{
blog:'0',
author:'1'
}
Copy the code
We can see that both array copy and object copy are different from what we expected, and the interaction between original data and new data is mutual. From this we can introduce the concept of shallow copy.
Shallow copy
Shallow copy is a bit-by-bit copy of an object. Creates a new object with an exact copy of the value in the original object. If any field of an object is a reference to another object, only the reference address is copied, that is, the memory address is copied. By default, reference types (object) are shallow copies.
The result of the copy is that both objects point to the same address, so if you change the properties of one object, the properties of the other object also change.
Deep copy
The deep copy copies all fields and dynamically allocated memory to which the fields point. Deep copy occurs when an object and the object it references are copied. Basic data types (number, String, NULL, undefined, Boolean) are deep-copied by default.
Deep copy creates A new stack, two objects correspond to two different addresses, and changing the properties of object A does not affect object B
Array deep copy scheme
Array deep copy can be implemented using the following methods
- use
slice()
- use
concat()
- ES6 extension operator
- Array.form()
let box = list.slice(); // let box = []. Concat (list); // let box = [...list]; // let box = array. from(list); / / fourCopy the code
Object. Assign problem for deep copy objects
Before we talk about deep copy, let’s look at object.assign ().
Looking at the following example, the results alone seem good
let B = Object.assign({},A);
Copy the code
But what if we make some changes?
Such as the following example
- Inside object A is nested A layer of object C,
- 【 modify 】A, b, C,
- 【 Result 】 At the same time that C in A is changed, B is also changed.
Object.assign() is a deep copy or a shallow copy?
define
The object.assign () method is used to assign the values of all enumerable properties from one or more source objects to target objects. It will return the target object. MDN document
For deep copy
Object.assign() copies (enumerable) property values. If the source value is a reference to an object, it simply copies its reference value.
Assign ({},Obj); if the Object attribute value is a simple type (such as Number, String), the new Object obtained by object.assign ({},Obj) is a deep copy. If the attribute value is an object or some other reference type, it is actually shallow-copied for that object.
Using destruct assignment and extension operators (…) You will find the same situation as above.
Object deep copy scheme
Using JSON. Stringify
Json.stringify converts the object to a string, json.parse converts the string to a new object,
Note: This method can only be used for objects that can be converted to JSON, not if the object contains function or RegExp.
let B = JSON.parse(JSON.stringify(A))
Copy the code
Using a recursive
Here are three things to note:
Use the new obj.constructor () function to create an empty object instead of {} or [], which preserves inheritance from the original chain.
2, use obj. HasOwnProperty (key) to check whether the property is from the prototype chain, because for.. in.. It also iterates through enumerable properties on its prototype chain.
3. The above function uses a recursive algorithm, which is fine if the function has a name and the name will never change. But the problem is that the execution of this function is tightly coupled with the name factorial. To eliminate this tight coupling, you need to use arguments.callee.
var clone = function (obj) {
if(obj === null) return null
if(typeof obj !== 'object') return obj;
if(obj.constructor===Date) return new Date(obj);
if(obj.constructor === RegExp) return new RegExp(obj);
var newObj = new obj.constructor (); //保持继承链
for (var key in obj) {
if (obj.hasOwnProperty(key)) { //不遍历其原型链上的属性
var val = obj[key];
newObj[key] = typeof val === 'object' ? arguments.callee(val) : val; // 使用arguments.callee解除与函数名的耦合
}
}
return newObj;
};
Copy the code
This method comes from: how to make a deep copy of objects in JS; To explore more deep-copy objects, take a look at this deep JS deep-copy object
Reference:
object.assign()-MDN
Shallow Vs Deep Copy In Javascript
Understanding Deep and Shallow Copy in Javascript
Leave a like if you get something! 😘