
深浅拷贝应该算是面试的高频考点之一,而且在工作中也会经常使用到。
浅拷贝
简单点说,浅拷贝: “如果一个对象或数组最外层元素的值是基本类型,那么拷贝的是该值,否则拷贝的是该引用。”
JavaScript 本身就提供了一些方法或操作来浅拷贝数组或对象。
比如 ES5 的 Object.assign()
,Array.prototype.slice()
,Array.prototype.concat()
ES6+ 的 Array.from()
和 …
扩展符
ℹ️ 建议:
除非是为了兼容旧浏览器,否则建议使用 ES6 语法,因为现在所有的主流浏览器都支持它。
而且现在的编码风格指南和最佳实践都推荐使用ES6,更用 Good和Bad来区分代码的好坏了。
更重要的是,ES6 的语法更加简洁,可读性更高。
如果是浅拷贝一个对象或数组,我们更多的是使用 ES6的 展开运算符 …
测试
浅拷贝一个对象
1 | const xiaoming = { name: '小明', profile: { address: 'ChansSha.China' } } |
浅拷贝一个数组
1 | const arr = [{ name: '小明' }, 24] |
我们发现,如果数组的元素是基本类型,就会直接拷贝元素的值;如果数组元素是引用类型,就会拷贝其引用;如果修改引用类型属性的值,则两者都会发生变化。
浅拷贝的实现
…
展开符只是一个语法糖,和 Array.from()
, Object.assing()
一样,只是 JavaScript 语言本身提供的便捷方法。
接下来我们思考一下应该如何实现对数组或对象的浅拷贝。
其实并不难,遍历对象,把对应的属性和值放到一个新的对象就行了。
让我们开始吧~
1 | function shallowCopy(obj){ |
深拷贝
顾名思义,深拷贝就是对一个对象的完全复制,无论它嵌套的层级有多深,新得到的对象与原来的对象彼此独立,互不影响。
那如何深拷贝一个对象呢?其实这里有一个小技巧,不仅适用于对象还适用于数组,额,其实它们都是对象子类型,真拗口~。
1 | const arr = [{ id: 1, name: 'xiaoming' }, { id: 2, name: 'huahua' }] |
我们轻而易举地深拷贝了一个数组,是不是很方便?
但是请小心,这种方法只适用于 JSON
安全的数据。
ℹ️ 像
undefined,function, symbol 以及 循环引用(对象之间互相引用)
都不符合 JSON 结构标准,支持 JSON 的语言无法处理它们。
JSON.stringify(…)
在对象中遇到 undefined
、
function
和 symbol
时会自动将其忽略,在数组中则会返回 null (以保证单元位置不变)。
举个栗子:
1 | console.log(JSON.parse(JSON.stringify([undefined, () => {}, Symbol(), 1]))) |
深拷贝的实现
那如何实现一个深拷贝呢?其实原理也很简单,和浅拷贝类似,只是多了一些步骤,我们在拷贝的时候判断一下属性值的类型,如果是引用类型,就递归地调用的深拷贝函数就行了。
1 | function deepCopy(obj){ |
不知道你发现了没有,我们似乎刻意忽略了函数,要知道函数也是一个对象子类型啊。
1 | const arr = { |
记得在《你不知道的JavaScript(上卷)》中这样说道:
我们还不确定“复制”一个函数意味着什么。有些人会通过
toString()
来序列化一个函数的源代码(但是结果取决与JavaScript的具体实现,而且不同的引擎对于不同类型的函数处理方式不完全相同)…(P109)
structuredClone()
在新的浏览器上已经可以使用内置的API structuredClone()
深拷贝JavaScript值了,
浏览器开始提供原生能力了,这是个令人振奋的消息。
浏览器兼容:
![]() |
![]() |
![]() |
![]() |
![]() |
---|---|---|---|---|
98 ✔ | 94 ✔ | 98 ✔ | 15.4 ✔ | 84 ✔ |
是的,这个 API 只能在新的浏览器中使用,如果你要应用在实际项目中,则需要做一些兼容性处理。
对于这个 structuredClone
解决了什么问题,有什么不足,我这里就不赘述了,可以参考下面的链接。
参考
https://github.com/mqyqingfeng/Blog/issues/33
https://web.dev/structured-clone/
https://developer.mozilla.org/en-US/docs/Web/API/structuredClone
- Post title:JavaScript专题之深浅拷贝
- Post author:w2xi
- Create time:2022-03-22 22:56:09
- Post link:https://w2xi.github.io/2022/03/22/JavaScript专题之深浅拷贝/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.