只拷贝了基本类型数据和引用类型数据的指针,叫浅拷贝
被拷贝的对象里,如果没有引用类型的数据,可以使用浅拷贝,方便快捷。
如果有引用类型,那么存在被篡改的风险,更应该使用深拷贝
1、手撸一个浅拷贝函数
1function shallowClone(obj) {
2 const newObj = {};
3 for(let prop in obj) {
4 if(obj.hasOwnProperty(prop)){
5 newObj[prop] = obj[prop];
6 }
7 }
8 return newObj;
9}
10
2、Object.assign / 展开运算符
1var obj = {
2 age: 18,
3 nature: ["smart", "good"],
4 names: {
5 name1: "fx",
6 name2: "xka"
7 },
8 love: function () {
9 console.log("fx is a great girl")
10 }
11}
12var newObj = Object.assign({}, fxObj);
13
3、数组的slice、concat方法
完全拷贝了基本类型和引用类型内部所有数据,叫深拷贝
1、JSON暴力转换
1const obj2=JSON.parse(JSON.stringify(obj1));
但是这种方式存在弊端,会忽略undefined、symbol、函数、正则。
1const obj = {
2 name: "A",
3 name1: undefined,
4 name2: /[a-zA-Z0-9]/g ,
5 name3: function() {},
6 name4: Symbol("A")
7}
8const obj2 = JSON.parse(JSON.stringify(obj));
9console.log(obj2); // {name: "A"}
2、手撸深拷贝函数(循环+递归)
1function deepClone(obj, hash = new WeakMap()) {
2 if (obj === null) return obj; // 如果是null或者undefined我就不进行拷贝操作
3 if (obj instanceof Date) return new Date(obj);
4 if (obj instanceof RegExp) return new RegExp(obj);
5 // 可能是对象或者普通的值 如果是函数的话是不需要深拷贝
6 if (typeof obj !== "object") return obj;
7 // 是对象的话就要进行深拷贝
8 if (hash.get(obj)) return hash.get(obj);
9 let cloneObj = new obj.constructor();
10 // 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身
11 hash.set(obj, cloneObj);
12 for (let key in obj) {
13 if (obj.hasOwnProperty(key)) {
14 // 实现一个递归拷贝
15 cloneObj[key] = deepClone(obj[key], hash);
16 }
17 }
18 return cloneObj;
19}
20