ItIron2021
Javascript
作者发烧中,但文章还是得发?
昨天的主题是关於js如何传递值,了解基本型别与物件间的差别是极端重要的概念,今天马上来一个应用题目吧!
请解释在JS中你要如何拷贝一个物件或是一个阵列
又是一个看起来很简单但一时间你可能回答不出来的题目对吧? 当碰到比较困难的题目时,我会先试着把题目做简化,我们先缩小题目的范围吧!
请解释在JS中你要如何拷贝一个阵列
有了昨天的教训,我们都很清楚下方的写法是会有问题的
let arr1 = [1, 2, 3]
let arr2 = arr1
这两个玩意有着相同的reference,你修改一个、另一个也会同样受到影响,所以这很明显是出局的,以下有几个常见的方法!
没错,就是你熟悉的for loop,这样最基础的做法往往最容易被人忽略
let arr1 = [1, 2, 3]
let arr2 = []
for (let i = 0; i < arr1.length; i++) {
arr2.push(arr1[i])
}
同样的道理,你当然也能用map或filter这样的语法糖去复制一个阵列!
另一个切入的方向就是利用js原生的一些方法去做到直接复制的效果,上述的两种方法也能很好的达成任务
let arr1 = [1, 2, 3]
let arr2 = [].concat(arr1)
let arr3 = arr1.slice()
arr2.push(4)
arr3.push(5)
console.log(arr1) // [1, 2, 3]
console.log(arr2) // [1, 2, 3, 4]
console.log(arr3) // [1, 2, 3, 5]
你可以看到三者确实已经是不同的reference了。
这玩意可说是我最喜欢的方法了,新加入的扩展运算子在许多地方都很实用,用来做阵列的复制与合并再适合不过了。
let arr1 = [1, 2, 3]
let arr2 = [...arr1] // [1, 2, 3]
这方法同样也适用於物件的复制
let obj1 = {
name: 'Danny',
age: 30
}
let obj2 = {
...obj1
}
上述的几种方法虽然都成功地复制了阵列/物件,但他们全都属於所谓的浅拷贝(shallow clone),也就是说万一你今天复制的对象里面还有其他的物件,里面的物件会还是保持同一个reference,我们看个简单的例子。
let demo = [0, [1, 2]]
let demoClone = demo.slice() // [0, [1, 2]]
demoClone[1].push(3)
console.log(demoClone) // [0, [1, 2, 3]]
console.log(demo) // [0, [1, 2, 3]]
上述的范例中虽然成功的复制了一维度的阵列,但里面的物件仍保有相同的reference,造成了你看到的结果,为了解决这样的问题,你需要的是深拷贝(deep clone),而在js中最简单做到深拷贝的办法就是先转成json字串再parse回来,原理大致上是因为字串属於基本型别,所以复制的时候会重新建立一个记忆体位置,其他的细节老样子自己去查?
let demo = [0, [1, 2]]
let demoClone = JSON.parse(JSON.stringify(demo))
demoClone[1].push(3)
console.log(demoClone) // [0, [1, 2, 3]]
console.log(demo) // [0, [1, 2]]
你可以看到,这麽一来连里面的物件参照也完全不同罗! 但这个方法有个小缺陷,由於是要转成json再转成字串储存,你原先的内容就要是合法的json数值,万一里面包含着函数就会直接掰掰了,这种时候你就要想办法去处理深拷贝罗! 但处理面试只要能回答以上几个方向基本上就完全没有问题了!
物件与阵列的复制方式都很接近,也就是回圈、型别既有语法以及扩展运算子,最终的大杀招就是转json字串再转回来做的深拷贝。
深拷贝 vs 浅拷贝、扩展运算子
本文章同步发布於个人部落格,有兴趣的朋友也可以来逛逛~!
>>: Day14 - 解决状态大爆炸 - 2: Hierarchical States (阶层式状态)
考量到要建立各种 class 所以统一建立一个 class 给所有人继承 可以直接跳过,但注意之後有...
今天作为这系列的结尾,我们来详细介绍这家位於卢森堡的新创公司AIVA的AI作曲服务。 AIVA AI...
Jetpack Compose 是 Google 开发的现代 Declarative UI fram...
今天要来聊聊 docker networking container 之间的 connect 是用网...
咦?我们都写完了,为什麽还不进入下一个专题呢? 啧啧,这你就不懂了!身为一个工程师,能动,只是交件标...