64

为什么在对象中传播未定义会返回一个空对象?{...undefined} // equals {}

console.log({...undefined})

为什么在数组中传播未定义会给你一个错误? [...undefined] // type error

console.log([...undefined])

4

3 回答 3

78

正如评论中所指出的,并由@ftor 从#687总结,对象传播相当于1Object.assign()(问题#687#45),而在数组文字上下文中传播是可迭代的传播。

引用Ecma-262 6.0Object.assign()定义为:

19.1.2.1 Object.assign(目标,...来源)

assign函数用于将所有可枚举自身属性的值从一个或多个源对象复制到目标对象。当调用assign函数时,会采取以下步骤:

  1. 让成为ToObject(目标)。
  2. ReturnIfAbrupt(到)。
  3. 如果只传递了一个参数,则返回。
  4. 让 sources 是从第二个参数开始的参数值列表。
  5. 对于每个元素 nextSource 的来源,按索引升序,执行
    1. 如果 nextSource 为undefinednull,则让 keys 为空List
    2. 别的, ...

...然后是复制自己的属性的描述。Object Rest/Spread Properties 的草案在这里。它不是 Ecma-262 6.0 的一部分。

数组文字表达式中的SpreadElement定义如下:

SpreadElement : ... 赋值表达式

  1. spreadRef是评估AssignmentExpression的结果。
  2. spreadObjGetValue ( spreadRef )。
  3. 迭代器GetIterator ( spreadObj )。
  4. ReturnIfAbrupt(迭代器)。

并且由于undefined没有带有键@@iterator的属性,因此根据GetIterator的步骤抛出TypeError。该标准不容易阅读,但如果我没记错的话,错误的路径是GetIterator -> GetMethod -> GetV -> ToObject,它会为 undefined 和 null 引发 TypeError。

在数组初始化中使用可能未定义值的变量的简单补救措施是使用默认值:

const maybeArray = undefined;
const newArray = [ ...(maybeArray || []) ];

1:在如何处理 setter 方面存在差异。

于 2017-11-07T11:30:15.280 回答
8

通常,...xrequiresx的使用是可迭代的,因为它的...目的通常是将可迭代的组件展平为它的组件。

但是,{...x} 需要x枚举,因为我们不仅需要值,还需要键和它们。

null是不可迭代的。它没有组件,因此迭代没有意义null。(for (const item of null)同样会失败。)

然而,null数的。null有时被视为对象,这是其中一种情况,对象是可枚举的,因为它们可以具有属性。(for (const prop in null)同样会成功。)

于 2020-07-13T23:32:34.900 回答
0

你可以使用这个表达式 [...(this.options || [])],其中 options 是数组

于 2022-01-11T13:19:16.543 回答