每日挑战,从Javascript面试题目了解一些你可能忽略的概念 - Day14

tags: ItIron2021 Javascript

前言

作者发烧中,但文章还是得发?
昨天的主题是关於js如何传递值,了解基本型别与物件间的差别是极端重要的概念,今天马上来一个应用题目吧!

本日题目与解释

请解释在JS中你要如何拷贝一个物件或是一个阵列

thinking-day14

又是一个看起来很简单但一时间你可能回答不出来的题目对吧? 当碰到比较困难的题目时,我会先试着把题目做简化,我们先缩小题目的范围吧!

请解释在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这样的语法糖去复制一个阵列!

  • slice or concat

另一个切入的方向就是利用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了。

  • 扩展运算子(spread operator)

这玩意可说是我最喜欢的方法了,新加入的扩展运算子在许多地方都很实用,用来做阵列的复制与合并再适合不过了。

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 浅拷贝、扩展运算子

总结

  • 了解复制阵列或物件的几种方法
  • 了解深浅拷贝间的差异
  • 了解转json字串的限制

本文章同步发布於个人部落格,有兴趣的朋友也可以来逛逛~!


<<:  Day 25 - 新鲜人协助面试新鲜人篇

>>:  Day14 - 解决状态大爆炸 - 2: Hierarchical States (阶层式状态)

[15] 建立 class 创建实例的继承

考量到要建立各种 class 所以统一建立一个 class 给所有人继承 可以直接跳过,但注意之後有...

Day 29: 人工智慧在音乐领域的应用 (卢森堡-AIVA)

今天作为这系列的结尾,我们来详细介绍这家位於卢森堡的新创公司AIVA的AI作曲服务。 AIVA AI...

Jetpack Compose intro

Jetpack Compose 是 Google 开发的现代 Declarative UI fram...

[13th][Day20] docker network

今天要来聊聊 docker networking container 之间的 connect 是用网...

Day 8 — 自动化回信机(5) 优化回信机

咦?我们都写完了,为什麽还不进入下一个专题呢? 啧啧,这你就不懂了!身为一个工程师,能动,只是交件标...