深浅拷贝
浅拷贝:只能拷贝最外部一层,深层的对象,依然是通过引用指向同一块堆内存。
简单实现
1
2
3
4
5
6
7function (obj) {
const newObj = {}
for (let i in obj) {
newObj[i] = obj[i]
}
return newObj;
}Object.assign()—该方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,它将返回目标对象。
1
2
3
4
5
6let a = {
name: 'test',
book: {price: '45'}
}
let b = Object.assign({}, a);扩展运算符
1
2let b = {...a};
// 与Object.assign()一样Array.prototype.slice()—方法返回一个新的数组对象,这一对象由begin和end(不包括end)决定原数组的浅拷贝。原始数组不会被改变。相应的还有
concat
操作不改变原数组1
2
3
4
5let a = [0, "1", [2,3]];
let b = a.slice(1);
console.log(b); // ["1", [2,3]]
a[2][0] = 4;
console.log(b); // ["1", [4,3]]
深拷贝
JSON.parse(JSON.stringify(object))
1
2
3
4
5
6let a = [0, "1", [2, 3]];
let b = JSON.parse(JSON.stringify( a.slice(大专栏 深拷贝class="number">1) ));
console.log(b);
// ["1", [2, 3]]
a[2][0] = 4;
console.log(b); // ["1", [2, 3]]深拷贝注意
- 循环引用,会报错
- new Date情况,转换结果不正确。函数、正则情况、symbol
- 会抛弃对象的constructor,深拷贝后不管对象原来的构造函数是什么,都会变成Object;
代码实现
1
2
3
4
5
6
7
8
9
10var deepCopy = function(obj){
if(typeof obj !== 'object')return;
var newObj = obj instanceof Array ? []: {};
for(var key in obj){
if(obj.hasOwnProperty(key)){
newObj[key] = typeof obj[key] === 'object'? deepCopy(obj[key]): obj[key]
}
}
return newObj;
}解决循环引用–设置一个哈希表存储已拷贝过的对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14var deepCopy = function(obj, hash= new WeakMap()){
if(typeof obj !== 'object')return;
// 查表
if (hash.has(obj))return hash.get(obj);
var newObj = obj instanceof Array ? []: {};
// 哈希表设值
hash.set(obj, newObj)
for(var key in obj){
if(obj.hasOwnProperty(key)){
newObj[key] = typeof obj[key] === 'object'? deepCopy(obj[key], hash): obj[key]
}
}
return newObj;
}