21.8 代码风格:空格在星号之前还是之后
合理的并且合法的放置星号的方式是:
- 星号两边保留空格:
function * foo(x, y) { ··· }
- 星号之前保留空格:
function *foo(x, y) { ··· }
- 星号之后保留空格:
function* foo(x, y) { ··· }
- 星号前后都没有空格:
function*foo(x, y) { ··· }
让我们指出哪种形式对于哪种解构来说是合理的,并且解释为什么。
21.8.1 生成器函数的声明和表达式
此处,使用星号的原因是因为 generator
(或者其它类似的单词)没有被用作关键字。如果可以作为关键字的话,那么生成器函数的声明就像这样子:
generator foo(x, y) {
···
}
ECMAScript 6 使用星号标记的 function
关键字来代替 generator
。因此, function*
可以看做是 generator
的同义词,这使得生成器函数声明的推荐写法就像下面这样。
function* foo(x, y) {
···
}
匿名生成器函数表达式的格式就像这样:
const foo = function* (x, y) {
···
}
21.8.2 生成器方法定义
当书写生成器方法定义的时候,我推荐如下的格式:
let obj = {
* generatorMethod(x, y) {
···
}
};
关于在星号之后放一个空格,有三个理由。
首先,星号不应该是方法名的一部分。一方面,它不是生成器函数名字的一部分。另一方面,仅在定义生成器的时候才会涉及到星号,在使用的时候并不会涉及到。
第二点,生成器方法定义是如下语法的缩写。(为了展现我的观点,我给函数表达式添加了多余的名字。)
let obj = {
generatorMethod: function* generatorMethod(x, y) {
···
}
};
如果方法定义要省略 function
关键字,那么星号后面就应该跟一个空格。
第三点,生成器方法定义在语法上类似于 getters
和 setters
(这两个语法在 ECMAScript 5 中就可用了):
let obj = {
get foo() {
···
}
set foo(value) {
···
}
};
关键字 get
和 set
可以看做普通方法定义的修饰器。同理,星号也是这样的一个修饰器。
21.8.3 用于嵌套调用的 yield 的书写格式
下面是一个 生成器函数通过 yield
递归调用自身的例子:
function* foo(x) {
···
yield* foo(x - 1);
···
}
星号标记出不一样的 yield
操作符,这就是为什么上面的代码是合理的的原因。
21.8.4 标记生成器函数和方法
Kyle Simpson ( @getify )提出了有趣的看法:在函数或方法调用的时候,我们经常会在后面加上括号,例如 Math.max()
,而对于生成器函数和方法而言,在前面加上星号不是更合理吗?例如:在上一子节我们不应该写成 *foo()
来表明是一个生成器的调用吗?让我来驳斥这个观点。
当需要调用一个返回可迭代对象的函数的时候,生成器是几个可选项中唯一的一个。我认为最好不要抛弃这种标记函数名的实现细节。
而且,在调用生成器函数的时候,你不会使用星号,但是使用了括号。
最后,星号并不会提供有用的信息 - yield*
也可用于返回可迭代对象的函数。但是标记返回可迭代对象的函数或方法名(包括生成器)可能是合理的。例如,加上 Iter
前缀。