茫茫人海中与你相遇
相信未来的你不会很差
原作者:Juan Cruz Martinez
原文链接:Write Cleaner Code by Using Javascript Destructuring
译者:zenblo
来源:https://juejin.cn/post/6901081096260648974#heading-0
解构是我最喜欢的 Javascript 特性之一。简单地说,解构可以将复杂结构(如数组或对象)分解为更简单的部分,虽然还有很多内容,但是相对简化了代码结构。
让我们通过一个例子来更好地了解:
const article = { title: "My Article", rating: 5, author: { name: "Juan", twitter: "@bajcmartinez" }}// 现在把它打印出来console.log(`"${article.title}" by ${article.author.name} had ${article.rating} stars`)// 通过使用解构同样能完成const { title, rating, author: { name } } = articleconsole.log(`"${title}" by ${name} had ${rating} stars`)------------------------Output------------------------"My Article" by Juan had 5 stars"My Article" by Juan had 5 stars
现在,一部分人已经采用解构开发了一段时间,或许是在构建 React 应用时候,但是他们并不完全了解它。对其他人来说,这可能是第一次用到解构。因此,本文将从头到尾完成整个过程,最终使得大家对解构的认知都能达到同一水平。
解构对象
在上面的例子中,所有隐藏的内容都发生在下面这行代码:
const { title, rating, author: { name } } = article
现在,在表达式左侧使用这样的大括号似乎有点奇怪,但这就是我们告诉 Javascript 正在分解对象的方式。
解构对象可以绑定到对象里的任一层级的任何属性上。让我们从一个更简单的示例开始:
const me = { name: "Juan"}const { name } = me
在上面的例子中,我们声明了一个名为 name
的变量,该变量将从对象 me
中获得相同名称的初始化属性,因此当我们对 name
求值时,我们得到 Juan
。太棒了!这个操作同样适用于任意层级的属性。回到我们的例子:
const { title, rating, author: { name } } = article
对于 title
和 rating
,和我们之前的讲解一样。但是在 author
这里,事情有点不同。当我们遇到一个是对象或数组的属性时,我们可以选择是创建一个变量author
的引用对象 article.author,或者进行深度解构并立即访问内部对象的属性。
访问对象属性:
const { author } = articleconsole.log(author.name)------------------------Output------------------------Juan
执行深度或嵌套解构:
const { author: { name } } = articleconsole.log(name)console.log(author)------------------------Output------------------------JuanUncaught ReferenceError: author is not defined
上面的示例怎么回事?如果解构了 author
,但是它为什么没有被定义?其实挺简单的。当我们要求 Javascript 也对 author
对象进行解构时,绑定本身并没有被创建,取而代之的是我们可以访问我们选择的所有author
属性,请记住这点。扩展运算符(...
):
const article = { title: "My Article", rating: 5, author: { name: "Juan", twitter: "@bajcmartinez"const { title, ...others } = articleconsole.log(title)console.log(others)------------------------Output------------------------My Article> {rating: 5, author: {name: "Juan", twitter: "@bajcmartinez" }}
此外,我们可以使用扩展运算符 ...
创建一个包含所有未被解构属性的对象。
如果你有兴趣了解更多关于扩展运算符的知识,请查看我的文章。
重命名属性
解构的一个重要特性是:能够为我们提取的属性选择不同的变量名。让我们看看下面的例子:
const me = { name: "Juan" }const { name: myName } = meconsole.log(myName)------------------------Output------------------------Juan
通过在一个属性上使用 :
我们可以为它提供一个新的名称(在我们的例子中是 newName
)。然后我们可以在代码中访问这个变量。需要注意的是,原始属性 name
的变量并没有被定义。
缺少属性
那么,如果我们试图解构一个没有在对象中定义的属性,会发生什么呢?
const { missing } = {}console.log(missing)------------------------Output------------------------undefined
在这种情况下,变量的值是 undefined
。
默认值
扩展缺失的属性,当属性不存在时,可以指定一个默认值。让我们来看一些例子:
const { missing = "missing default" } = {}const { someUndefined = "undefined default" } = { someUndefined: undefined }const { someNull = "null default" } = { someNull: null }const { someString = "undefined default" } = { someString: "some string here" }console.log(missing)console.log(someUndefined)console.log(someNull)------------------------Output------------------------missing defaultundefined defaultnullsome string here
这些都是解构对象赋值的例子,默认值仅在属性 undefined
分配。例如,如果属性的值为 null
或 string
,则不会分配默认值,但属性的实际值会被分配。
解构数组和可迭代对象
我们已经看到了一些解构对象的例子,但是同样的例子也适用于数组或可迭代对象。让我们从一个例子开始:
const arr = [1, 2, 3]const [a, b] = arrconsole.log(a)console.log(b)------------------------Output------------------------12
当我们需要解构一个数组时,我们需要使用 []
而不是 {}
,我们可以用不同的变量映射数组的每个位置。但是也有一些不错的方法:
跳过元素
通过使用 ,
运算符,我们可以跳过可迭代数据项中的一些元素,如下所示:
const arr = [1, 2, 3]const [a,, b] = arrconsole.log(a)console.log(b)------------------------Output------------------------13
请注意,在 ,
之间留一个空格会跳过元素。这是小细节,但对结果有很大影响。你还能做什么?你也可以使用扩展运算符 ...
进行如下操作:
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]const [a,, b, ...z] = arrconsole.log(a)console.log(b)console.log(z)------------------------Output------------------------13(7) [4, 5, 6, 7, 8, 9, 10]
在这种情况下,z
将获得 b
之后的所有值成为数组。或者你有一个更具体的需求,你想在数组中的特定位置解构。没问题,Javascript 依然可以做到:
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]const { 4: fourth, 9: ninth } = arrconsole.log(fourth)console.log(ninth)------------------------Output------------------------510
如果我们把一个数组当作一个对象来解构,我们可以把索引作为属性,来访问数组中的任何位置的值。
缺少属性
与对象的情况一样,也可以为数组中未定义的元素设置默认值。让我们看一些例子:
const [missing = 'default missing'] = []const [a, b, c = "missing c", ...others] = [1, 2]console.log(missing)console.log(a)console.log(b)console.log(c)console.log(others)------------------------Output------------------------default missing12missing c[]
当解构数组时,也可以为 undefined
属性设置默认值。但是,当我们使用扩展运算符...
时,则不能为变量设置默认值。在使用 ...
解构 undefined
时,它将返回一个空数组:
交换变量
这是一个有趣的解构示例。在一个表达式中可以交换两个变量:
let a = 1let b = 5[a, b] = [b, a]console.log(a)console.log(b)------------------------Output------------------------51
使用计算属性进行解构
直到现在,任何时候我们想要解构一个对象的属性或者一个可迭代的元素,我们都使用静态键。如果我们想要动态键(比如存储在变量中的键),我们需要使用计算属性:
这里有一个示例:
const me = { name: "Juan" }let dynamicVar = 'name'let { [dynamicVar]: myName } = meconsole.log(myName)------------------------Output------------------------Juan
通过在 []
中使用变量,我们可以在赋值之前计算它的值。因此,尽管必须为该新变量提供名称,但可以进行动态解构。
解构函数参数
解构变量可以在我们声明变量的任何地方使用(例如,通过使用 let
、const
或 var
),也可以解构函数参数。这是一个简单的示例:
const me = { name: "Juan" }function printName({ name }) { console.log(name)}printName(me)------------------------Output------------------------Juan
非常简单。此外,我们之前讨论过的所有规则都适用。
结论
在开始使用解构时可能会不舒服,但一旦你习惯了,就再也回不去了。它真的可以让你的代码更简洁,这是一个需要了解的概念。
我们在虚拟的空间与你相遇,期待可以碰撞出不一样的火花
公众号ID:前端大联盟扫码关注最新动态