JavaScript扩展运算符搭配条件表达式为何对象正常数组报错
语法差异核心原因
两种场景下的扩展运算符根本不是同一套语法实现,遵循的规范完全不一样,对传入值的要求天差地别。
对象字面量的扩展规则
对象里的...是ES2018才加入的语法,逻辑很简单:把后面跟的值转成对象,把它身上所有自身可枚举的属性挨个抄到新对象里。
- 布尔值、null、undefined、数字这类原始值转成对应的包装对象后,根本没有自己的可枚举属性,展开的时候啥也抄不到,自然不会报错,也不会往新对象里加任何内容。
你可以直接试:console.log({...false}),输出就是纯空对象{},不会有任何异常。你示例里(false && { bar: 'baz' })算出来就是false,展开它等于啥都没加,所以代码能正常跑,最后对象里只剩foo: 'bar'。
数组字面量的扩展规则
数组、函数传参里用的...是ES2015就有的语法,它的运行完全依赖可迭代协议:引擎会先找后面跟的值的Symbol.iterator方法,调用这个方法拿到迭代器,再逐个遍历迭代器返回的值塞进数组。
- 如果后面跟的值没有
Symbol.iterator属性(也就是不是可迭代类型),引擎直接就抛TypeError,不会做任何容错处理。
false是布尔原始值,压根没实现可迭代协议,自然一展开就报「not iterable」的错,和你遇到的报错完全对应。
数组条件展开的正确写法
想在数组里实现和对象一样的条件按需展开效果,别让条件分支返回布尔值,条件不满足的时候返回空数组就行:
console.log([ 'foo', ...(true && ['bar']), ...(false ? ['baz'] : []), ]); // 运行结果:['foo', 'bar']
内容的提问来源于stack exchange,提问作者gremo
相关产品推荐
相关产品推荐

