真正的情谊,无关风月,纤尘不染,只因你在,我也在,你未离,我亦未弃。羁绊,本就如此简单。
浅拷贝
- 浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址。
深拷贝
- 深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存。
理解
- 深拷贝和浅拷贝最根本的区别在于是否真正获取一个对象的复制实体,而不是引用。
- 假设 B 复制了 A,修改 A 的时候,看 B 是否发生变化,如果 B 跟着也变了,说明是浅拷贝,反之为深拷贝。
- 深拷贝是先开辟出一块空间,再将值拷贝进去。
数组拷贝操作
- 直接赋值
1 | let a = [1, 2, [3, 4]]; |
- 原数组和复制数组值同时改变,为浅拷贝
- 直接修改原数组值的方法 pop reverse shift unshift push splice
1 | let a = [1, 2, [3, 4]]; |
- 直接修改原数组的方法,无拷贝
- 扩展运算符、slice、 concat
1 | let a = [1, 2, [3, 4]]; |
- 当原数组为一维数组的时候,使用以上方法,修改复制数组,不改变原数组,为深拷贝
- 当原数组为二维数组的时候,使用以上方法,修改复制数组数组内的数组,会改变原数组数组内的数组,为浅拷贝
- join、flat 、String
1 | let a = [1, 2, [3, 4]]; |
- 以上复制改变了数组维度或者数据类型,不会影响到原数组,但是会存在丢失原数组的问题
- map 、forEach
1 | let a = [1, 2, [3, 4]]; |
- 和扩展运算符一样只能第一层数组改变不会改变原数组
- JSON 转化
1 | let a = [1, 2, [3, 4], { name: '小华' }, () => console.log('1')]; |
- 经过 json 转化的复制数组,修改多层不会影响到原数组,但是转化过程会存在丢失原数组的问题
- 递归
1 | let a = [1, 2, [3, 4], { name: '小华' }, () => console.log('1')]; |
- 递归遍历复制数组,修改多层不会影响到原数组,也不会丢失数组项
对象拷贝操作
- 直接赋值
1 | let obj = { name: '小明', function: () => console.log('1'), age: 23, say: { like: '运动' } }; |
- 原对象和复制对象值同时改变,为浅拷贝
- Object.assign
1 | let obj = { name: '小明', function: () => console.log('1'), age: 23, say: { like: '运动' } }; |
- 原对象和复制对象值同时改变,为浅拷贝
- 扩展运算符
1 | let obj = { name: '小明', function: () => console.log('1'), age: 23, say: { like: '运动' } }; |
- 当原对象只有一层的时候,使用以上方法,修改复制对象,不改变原对象,为深拷贝
- 当原对象超过一层的时候,使用以上方法,修改复制对象第二层内的值,会改变原对象第二层内的值,为浅拷贝
- for/in
1 | let obj = { name: '小明', function: () => console.log('1'), age: 23, say: { like: '运动' } }; |
- 当原对象只有一层的时候,使用以上方法,修改复制对象,不改变原对象,为深拷贝
- 当原对象超过一层的时候,使用以上方法,修改复制对象第二层内的值,会改变原对象第二层内的值,为浅拷贝
- JSON 转化
1 | let obj = { name: '小明', function: () => console.log('1'), age: 23, say: { like: '运动' } }; |
- 经过 json 转化的复制对象,修改多层不会影响到原对象,但是转化过程会存在丢失对象的问题
- 递归
1 | let obj = { name: '小明', function: () => console.log('1'), age: 23, say: { like: '运动' } }; |
- 递归遍历复制对象,修改多层不会影响到原对象,也不会丢失对象值