Quick JS understanding of deep and shallow copy
自我记录
In layman's terms, copying means copying. Ps: This article is just a personal opinion and summary. If you have different opinions, you can point them out in the comment area and learn together! First of all, I want to understand, , I think I need to
know深拷贝
a浅拷贝
few4
knowledge points about JS basics数据类型
,引用类型
,栈
,堆
If you want to use it directly, you can directly Look4.1
,4.2
,4.3
(dark copy) The reason why there is so much ink is that we should not only be able to use it but also know some principles. It
4.1
is...
the ES6 expansion operator (light),
4.2
it isObject.assign(target,sources)
the ES6 method (light),
4.3
it isJSON.parse(JSON.stringify(对象))
the serialization and deserialization method (deep)
1. JS data types
1.1 Basic data types (7)
1.Number(数值,包含NaN)
2.String(字符串)
3.Boolean(布尔值)
4.Undefined(未定义/未初始化)
5.Null(空对象)
6.Symbol(独一无二的值,ES6 新增)
7.BigInt (任意精度格式的整数,能够表示超过 Number 类型大小限制的整数,ES10新增)
1.2 Reference types
1.Object(包含Array、Function等)
1.3 Differences between basic data types and reference types
(1).Basic data type (stored in 栈
)
Basic data types refer to those stored in
栈
. They are stored简单数据段,数据大小确定,内存空间大小可以分配
directly , so they can be accessed directly.值
值
(2).Reference type (stored in 堆
)
The reference data type
栈
is stored指针(一个地址)
in指针指向堆
the entity起始地址
. When the interpreter looks for a reference value, it first retrieves its栈
address in the object, and then obtains the entity from the heap after obtaining the address.
2. Stack and heap in memory
2.1 What is a stack
First in, last out; automatically allocated and released by the operating system to store function parameter values, local variable values, etc. It operates like a stack in a data structure.
2.2 What is a heap?
Queue priority, first in first out; dynamically allocated space is generally allocated and released by the programmer. If the programmer does not release it, it may be reclaimed by the OS when the program ends. The allocation method is similar to a linked list.
2.3 Summary of differences
Personally, I understand it from the perspective of this article: 基本数据类型在栈里面存的是值
, 引用类型在栈里面存的是一个指针
(it feels like an address) is used to 指向对应堆里面的这个地址
involve shallow copy and deep copy.
For detailed overview, please refer to other articles online.
3. Shallow copy and deep copy
1. Assignment
基本数据类型
means栈中的值
copying is given, but what引用类型
is assigned is栈中对应堆的的地址
, and不是堆中的数据
. That is to say, the two objects point to the fact同一个存储空间
that no matter which object changes, it is actually the content of the changed storage space. Therefore, the two objects are linked. Once one party is modified, the other party will also be affected.
2. Therefore: there is no shallow/deep copy of basic data types
3.1 Shallow copy
As mentioned earlier, when defining an object or array, variables store only
一个地址
. When we use object copy, if the attribute is对象
or数组
, what we pass at this time is only一个地址
. Therefore, when the child object accesses this attribute, it will trace back to the address pointed to by the parent object堆内存中
, that is, if the parent and child objects occur关联
, the attribute values of both will be the same指向同一内存空间联动
.
Simple understanding: Shallow copy is to copy only one layer of data.
Common methods are:...
andObject.assign(target,sources)
3.2 Deep copy
An identical object will be created. The new object does not share memory with the original object, and modifications to the new object will not change the original object.
4. Three ways to share commonly used copies
4.1 ES6 spread operator (shallow copy)
There is no shallow copy as follows:
// 没有进行深拷贝
let a = [1, 2, 3]
let b = a
a[0] = 100
console.log(a) // [100, 2, 3]
console.log(b) // [100, 2, 3]
Use ...
shallow copy as follows:针对只有一层数据
// 进行浅拷贝
let a = [1, 2, 3]
let b = [...a]
a[0] = 100
console.log(a) // [100, 2, 3]
console.log(b) // [1, 2, 3]
Multi-layer data structures such as two-dimensional arrays can only be modified by this method.第一层
// 只拷贝了一层数据
let a = [1, 2, 3, [40, 50]]
let b = [...a]
a[0] = 10
a[3][0] = 400
console.log(a) // [10, 2, 3, [400, 50]]
console.log(b) // [1, 2, 3, [400, 50]]
4.2 ES6 Object.assign(target,sources)(浅拷贝)
There is no shallow copy as follows:
// 没有进行深拷贝
let a = [1, 2, 3]
let b = a
a[0] = 100
console.log(a) // [100, 2, 3]
console.log(b) // [100, 2, 3]
Use Object.assign
shallow copy as follows:针对只有一层数据
// 进行浅拷贝
let a = [1, 2, 3]
let b = Object.assign([], a)
a[0] = 100
console.log(a) // [100, 2, 3]
console.log(b) // [1, 2, 3]
Multi-layer data structures such as two-dimensional arrays can only be modified by this method.第一层
// 只拷贝了一层数据
let a = [1, 2, 3, [40, 50]]
let b = Object.assign([], a)
a[0] = 10
a[3][0] = 400
console.log(a) // [10, 2, 3, [400, 50]]
console.log(b) // [1, 2, 3, [400, 50]]
If you want to avoid changes, you cannot share xx002. It can also be understood that the heap of b uses xx003 and xx004.
Obviously the expansion operator cannot be implemented.
4.3 Serialization and deserialization method (deep copy)
JSON.parse(JSON.stringify(对象))
let a = [1, 2, 3, [40, 50]]
let b = JSON.parse(JSON.stringify(a))
a[0] = 10
a[3][0] = 400
console.log(a, 'a') // [10, 2, 3, [400, 50]]
console.log(b, 'b') // [1, 2, 3, [40, 50]]
4.4 Recursion (deep copy)
只考虑数据层面
// 递归
function fnDeepCopy(newObj, obj) {
// 遍历对象
for (key in obj) {
// newObj[key] = obj[key] 拷贝一层
// 如果obj[key] 是数组,又要重新遍历数组拷贝,在如果obj[key]是对象也要重新遍历拷贝,否则就直接拷贝一层
if (obj[key] instanceof Array) {
// 先判断数组,因为Array也是对象的一种
newObj[key] = []
fnDeepCopy(newObj[key], obj[key])
} else if (obj[key] instanceof Object) {
newObj[key] = {
}
fnDeepCopy(newObj[key], obj[key])
} else {
newObj[key] = obj[key]
}
}
}
let a = [1, 2, 3, [40, 50]]
let b = []
fnDeepCopy(b, a)
a[0] = 10
a[3][0] = 400
console.log(a) // [10, 2, 3, [400, 50]]
console.log(b) // [1, 2, 3, [40, 50]]
It is not easy to summarize, but I hope it will be helpful to you. I hope we can learn and make progress together. (Likes and collections are my motivation) The above are the
two methods I commonly use.
By the way, I will share what a big guy said: deep js deep copy object: https ://www.jianshu.com/p/b08bc61714c7