Get to know MDN better
此页面由社区从英文翻译而来。了解更多并加入 MDN Web Docs 社区。
解构语法是一种 Javascript 语法。可以将数组中的值或对象的属性取出,赋值给其他变量。它可以在接收数据的位置使用(例如赋值的左侧或创建新标识符绑定的任何位置)。
对象和数组字面量表达式提供了一种简单的方法来创建临时的数据包。
解构使用类似的语法,但在赋值的左侧定义了要从原变量中取出哪些值。
同样,你可以在赋值语句的左侧解构对象。
这种功能类似于 Perl 和 Python 等语言中存在的特性。
有关数组或对象解构的特定功能,请参阅下面的各个示例。
对于对象和数组的解构,有两种解构模式:绑定模式和赋值模式,它们的语法略有不同。
在绑定模式中,模式以声明关键字(var、let 或 const)开始。然后,每个单独的属性必须绑定到一个变量或进一步解构。
所有变量共享相同的声明,因此,如果你希望某些变量可重新分配,而其他变量是只读的,则可能需要解构两次——一次使用 let,一次使用 const。
你也可以在其他许多为你绑定变量的语法中,使用绑定解构模式。这些包括:
在赋值模式中,模式不以关键字开头。每个解构属性都被赋值给一个赋值目标——这个赋值目标可以事先用 var 或 let 声明,也可以是另一个对象的属性——一般来说,可以是任何可以出现在赋值表达式左侧的东西。
备注:当使用对象字面量解构而不带声明时,在赋值语句周围必须添加括号 ( ... )。
{ a, b } = { a: 1, b: 2 } 不是有效的独立语法,因为左侧的 {a, b} 被视为块而不是对象字面量。但是,({ a, b } = { a: 1, b: 2 }) 是有效的,const { a, b } = { a: 1, b: 2 } 也是有效的。
如果你的编码风格不包括尾随分号,则 ( ... ) 表达式前面需要有一个分号,否则它可能用于执行前一行的函数。
请注意,上述代码在等效的绑定模式中不是有效的语法:
你只能在赋值运算符的左侧使用赋值模式。不能与复合赋值运算符如 += 或 *= 一起使用。
每个解构属性都可以有一个默认值。当属性不存在或值为 undefined 时,将使用默认值。如果属性的值为 null,则不使用默认值。
默认值可以是任何表达式。仅在必要时对其进行求值。
你可以使用剩余属性(...rest)结束解构模式。对数组解构时,此模式会将数组的剩余元素存储到新的名为 rest(或在代码中指定的其他名字)的数组中。对对象解构时,此模式会将对象剩余的可枚举属性存储到新的名为 rest 的对象中。
更正式的说,...rest 语法在数组解构中被称作“剩余元素”,在对象解构中被称作“剩余属性”,但我们通常统称其为“剩余属性”。
剩余属性必须是模式中的最后一个,并且不能有尾随逗号。
在从赋值语句右侧指定的长度为 N 的数组解构的数组中,如果赋值语句左侧指定的变量数量大于 N,则只有前 N 个变量被赋值。其余变量的值将是未定义。
可以在一个解构表达式中交换两个变量的值。
没有解构的情况下,交换两个变量需要一个临时变量(或者用低级语言中的异或交换技巧)。
从一个函数返回一个数组是十分常见的情况。解构使得处理返回值为数组时更加方便。
在下面例子中,要让 f() 返回值 [1, 2] 作为其输出,可以使用解构在一行内完成解析。
你可以忽略你不感兴趣的返回值:
你也可以忽略全部返回值:
数组解构的剩余属性可以是另一个数组或对象绑定模式。这允许你同时提取数组的属性和索引。
这些绑定模式甚至可以嵌套,只要每个剩余属性都在列表的最后。
另一方面,对象解构只能有一个标识符作为剩余属性。
当正则表达式的 exec() 方法找到匹配项时,它将返回一个数组,该数组首先包含字符串的整个匹配部分,然后返回与正则表达式中每个括号组匹配的字符串部分。解构允许你轻易地提取出需要的部分,如果不需要,则忽略完整匹配。
数组解构调用右侧的迭代协议。因此,任何可迭代对象(不一定是数组)都可以解构。
不可迭代对象不能解构为数组。
只有在分配所有绑定之前,才会迭代可迭代对象。
其余的绑定会提前求值并创建一个新数组,而不是使用旧的迭代器。
可以从对象中提取属性,并将其赋值给名称与对象属性不同的变量。
举个例子,const { p: foo } = o 从对象 o 中获取名为 p 的属性,并将其赋值给名为 foo 的局部变量。
一个属性可以同时是两者:
传递给函数参数的对象也可以提取到变量中,然后可以在函数体内访问这些变量。至于对象赋值,解构语法允许新变量具有与原始属性相同或不同的名称,并为原始对象未定义属性的情况分配默认值。
请考虑此对象,其中包含有关用户的信息。
在这里,我们展示了如何将传递对象的属性提取到具有相同名称的变量。参数值 { id } 表示传递给函数的对象的 id 属性应该被提取到一个同名变量中,然后可以在函数中使用。
你可以定义提取变量的名称。在这里,我们提取名为 displayName 的属性,并将其重命名为 dname,以便在函数体内使用。
嵌套对象也可以提取。下面的示例展示了属性 fullname.firstName 被提取到名为 name 的变量中。
默认值可以使用 = 指定,如果指定的属性在传递的对象中不存在,则将其用作变量值。
下面我们展示了一个默认大小为 big的函数,默认坐标为 x: 0, y: 0,默认半径为 25。
在上面 drawChart 的函数签名中,解构的左侧具有空对象 = {} 的默认值。
你也可以在没有该默认值的情况下编写该函数。但是,如果你省略该默认值,该函数将在调用时寻找至少一个参数来提供,而在当前形式下,你可以在不提供任何参数的情况下调用 drawChart()。否则,你至少需要提供一个空对象字面量。
有关详细信息,请参阅默认参数值 > 有默认值的解构参数。
计算属性名,如对象字面量,可以被解构。
通过提供有效的替代标识符,解构可以与不是有效的 JavaScript 标识符的属性名称一起使用。
对象解构几乎等同于属性访问。这意味着,如果尝试解构基本类型的值,该值将被包装到相应的包装器对象中,并且在包装器对象上访问该属性。
与访问属性相同,解构 null 或 undefined 会抛出 TypeError。
即使模式为空,也会发生这种情况。
数组和对象解构可以组合使用。假设你想要下面 props 数组中的第三个元素,然后你想要对象中的 name 属性,你可以执行以下操作:
当解构一个对象时,如果属性本身没有被访问,它将沿着原型链继续查找。
| ECMAScript® 2027 Language Specification # sec-destructuring-assignment |
| ECMAScript® 2027 Language Specification # sec-destructuring-binding-patterns |
启用 JavaScript 以查看此浏览器兼容性表。