-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
关于 JavaScript 中的深拷贝 #23
Comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
写在前面
一般而言,js 中的浅拷贝和深拷贝主要针对 object、array 这些更为复杂的数据类型,而在日常使用中浅拷贝使用更为频繁,以及相比于深拷贝,浅拷贝非常容易懂且问题少的多。
浅拷贝
浅拷贝:只是复制了对象属性的引用,如果原对象改变了,目标对象也会跟着改变
深拷贝
先分别看看 Array 和 Object 自有的方法支持不?
Array
此时
arr2
的修改并没有影响到arr1
,将arr1
改成二维数组再来看看:arr2
又跟arr1
一样了,看来slice
只能修改一维数组。具备同等特性的还有:concat, Array.from。
Object
Object.assign()
Object.assign() 只能实现一维对象的深拷贝
JSON.parse(JSON.stringify(obj))
JSON.parse(JSON.stringify(obj))
看起来可以实现二维对象的深拷贝,不过 MDN有句话描述的很清楚。将
obj1
改造下你会发现,在将
obj1 进行 JSON.stringify()
序列化的过程中,y,z,a 被忽略了,也验证了 MDN 文档上的描述。因此,JSON.parse(JSON.stringify(obj))
使用起来也有局限性。不能深拷贝含有 undefined,function,Symbol 值的对象。不过JSON.parse(JSON.stringify(obj))
已经满足我们大部分使用场景了。深拷贝: 是对象的层级复制,也就是说目标对象和原对象完全不相干。
上面提到的 javascript 自有方法并不能彻底解决 Array,Object 的深拷贝问题,只能使用递归了。
可以看到,递归可以完美地解决了前面的遗留问题,我们也可以使用第三方库:jQuery 的
$.extend
和 loadash 的_.cloneDeep
来解决深拷贝。上面虽然是用 Object 验证,但对于 Array 也同样适用,因为 Array 也是特殊的 Object。但是还有一个非常特殊的场景:
循环引用拷贝
此时如果调用刚才的 deepCopy 函数的话,会陷入一个循环的递归过程,从而导致爆栈。jQuery 的
$.extend
也没有解决,解决这个问题:需要判断一个对象的字段是否引用这个对象或这个对象的任意父级即可,修改代码如下:// 另外一种深拷贝实现
深拷贝与浅拷贝的概念只存在于引用类型
The text was updated successfully, but these errors were encountered: