对象复制
学习前提:了解 js 的数据类型
基本数据类型(7) | 引用数据类型(5) |
---|---|
Number | Object |
String | Function |
Boolean | Array |
Null | Date |
Undefined | RegExp |
BigInt | – |
Symbol | – |
浅拷贝
理解:浅拷贝复制的是对象的引用地址,没有开辟新的栈,复制的结果是两个对象指向同一个地址,所以修改其中一个对象的属性,另一个对象的属性也跟着改变了。
- 对象浅拷贝
// 方案一:使用Object.assign方法
var obj1 = {a: 1, b: 2}
var obj2 = Object.assign({}, obj1)
// 方案二:结构赋值
var obj1 = {a: 1, b: 2}
var obj2 = {...obj1}
深拷贝
理解:深拷贝会开辟新的栈,两个对象对应两个不同的地址,修改对象 A 的属性,并不会影响到对象 B
- 数组深拷贝
// 方案一:使用 slice 方法 let box = list.slice(); // 方案二:使用 concat 方法 let box = [].concat(list); // 方案三:使用 es6 的扩展运算符 let box = [...list]; // 方案四:使用 Array.from 方法 let box = Array.from(list);
- 对象深拷贝
// 方案一:使用 JSON.parse(JSON.stringify(obj)) // 注意:如果对象中包含 function 或 RegExp 或者值为 undefined 则不能使用该方案 let box = JSON.parse(JSON.stringify(obj)); // 方案二:使用 lodash-es 的 cloneDeep 方法 import { cloneDeep } from 'lodash-es'; let box = cloneDeep(obj); // 方案三:使用递归 function clone(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 解除与函数名的耦合,相当于 clone(val) } } return newObj; }