js - 浅拷贝和深拷贝
在项目中,经常会用到拷贝。
浅拷贝和深拷贝,相信大家都知道区别,但是怎么去实现呢?
我会分享一些项目中经常会用到的一些方法,然后再手写一个深/浅拷贝的方法。
1. Object.assign
相信这个很多人都用过,用过就知道,这个在微信端,ie11或更低版本的ie上并不支持。所以我们就抛弃了这种方法。
这种方法也只是浅拷贝,不能满足深拷贝的需求
2. 通过es6的扩展运算符...来实现浅拷贝
let a = { age: 1 } let b = { ...a } a.age = 2 console.log(b.age) // 1
通常,浅拷贝只能解决部分问题。所以我们来看看深拷贝。
3. JSON.parse(JSON.stringify(object))
这个方法在项目中用的挺多的。
let a = { age: 1, jobs: { first: 'FE' } } let b = JSON.parse(JSON.stringify(a)) a.jobs.first = 'native' console.log(b.jobs.first) // FE
但是该方法有局限性:
- 会忽略
undefined
- 会忽略
symbol
- 不能序列化函数
- 不能解决循环引用的对象
自己实现一个深拷贝是很困难的,因为有很多便捷情况需要考虑。比如原型链,dom如何处理。所以我是根据项目实现的一个简易版的深、浅拷贝。
推荐一个库: lodash
var isObject = function(obj) { return obj !== null && (typeof obj === "object" || typeof obj === "function") }; var clone = function(obj, deep) { if (!isObject(obj)) { throw new Error(obj + " is not object"); } var newObj; var cloneArray = function(item) { var newItem = []; var size = item.length; for (var i = 0; i < size; i++) { var vk = item[i]; if (deep && isObject(vk)) { newItem[i] = clone(vk, deep); } else { newItem[i] = vk; } } return newItem; }; var cloneObject = function(item) { var newItem = {}; Object.keys(item).forEach(function(n) { var v = item[n]; if (deep && isObject(v)) { newItem[n] = clone(v, deep); } else { newItem[n] = v; } }); return newItem; }; if (obj instanceof Array) { newObj = cloneArray(obj); return newObj; } newObj = cloneObject(obj); return newObj; }
测试代码:
var obj1 = { a: 1, b: ["a", "b"] }; var obj2 = { b: 2, c: obj1 }; var obj3 = clone(obj2, true); var obj4 = clone(obj2, false); obj1.b = ["a", "b", "c"]; obj1.a = "2"; console.log(obj3); console.log(obj4);
输出结果:
从结果可以看出:
深拷贝obj3的结果不会因为引用类型obj1的改变而改变
浅拷贝obj4的结果会因为引用类型obj1的改变而改变