语法的其他用途
主要答案中未涵盖传播/休息语法的其他众多用途。它们包括:
- 函数参数中的 Rest 语法
- 数组和对象1解构赋值
- 对象字面量中的对象扩展语法1
休息语法
扩展语法的用法,通常称为rest 语法,用于函数的参数 中可变数量的参数。这与散布参数不同,散布参数用于将参数传递给基于可迭代元素的函数调用。例如:
function add(...addends) {
…
}
这里,rest 语法用于函数add 接收标识符addends 中参数的rest。这似乎确实评估为奇异值,因为 addends 是传递参数的数组,但如果我们尝试一下:
function foo(...[bar, baz]) {
…
}
在这里,bar 和 baz 都将被分配一个对应于传递的第一个和第二个参数的值——因此这并不总是评估为一个值。根本问题是第一个示例中的...addends 和第二个示例中的...[bar, baz] 实际上根本没有计算出一个值——它只是在将参数数组分配给标识符的操作期间使用。因此,它的语法允许函数的参数数量可变,而不是运算符。
解构赋值
spread 语法也可以在array destructuring assignment 期间使用,实际上在语言规范中被称为休息元素(因为在解构中使用时,它会获得解构后的迭代的其余部分)。可以提出一个令人信服的论点,因为这看起来确实像一个运算符:
const [...bar] = [1, 2, 3];
它被用作前缀一元运算符。这里,bar 的计算结果为 [1, 2, 3] — ,这是一个单一值。但这并不总是发生,例如:
const [first, ...[second, third]] = [1, 2, 3];
在这里,first、second 和 third 分别计算为 1、2 和 3。但是...[second, third] 分配给两个标识符,而不是一个,并且不会评估为一个奇异值,而是两个。就像 rest 语法一样,根本问题是第一个示例中的 ...bar 和第二个示例中的 ...[second, third] 实际上根本没有计算出一个值——它只是在任务。因此,它根本不是一个运算符2,只是帮助解包值的新语法。
对象传播语法
扩展语法的最终用途是在对象字面量中,通常称为“对象扩展属性”,其中目标对象自己的可枚举属性传播到另一个对象,例如:
const foo = { ...bar };
这不是运算符,就像数组扩展语法不是运算符一样。概念是一样的,而不是数组中的索引和元素,bar 的可枚举键和值传播到foo。在这里,bar 的属性的集合是散布的——不仅仅是一个单一的值,因此它不符合运算符的定义。
1Object rest/spread properties 目前处于 ECMAScript 的第 3 阶段提案中,很可能会在不久的将来添加
2 除了语义之外,将解构赋值作为运算符的另一个问题是the language specification 将其定义为补充语法—— 不是补充运算符,这是理所当然的。它不是独立的,因为这不起作用:
const ...bar = [1, 2, 3, 4];
它是上下文相关的,只有语言的语法、对象字面量和左侧表达式的数组字面量才允许存在。它也是改进左侧表达式解释的语法。同样,这是向语言添加新 语法 的扩展,是对现有语法的改进。这再次证实了规范的论点。