通常,我会编写如下代码:
//definition
exports.getReply = function * (msg){
//...
return reply;
}
//usage
var msg = yield getReply ('hello');
但是如何在es6类中编写和使用生成器呢?我试过这个:
class Reply{
*getReply (msg){
//...
return reply;
}
*otherFun(){
this.getReply(); //`this` seem to have no access to `getReply`
}
}
var Reply = new Reply();
Reply.getReply(); //out of class,how can I get access to `getReply`?
我也尝试过:
class Reply{
getReply(){
return function*(msg){
//...
return reply;
}
}
}
所有这两种方法似乎都是错误的答案。那么如何正确地在类中编写生成器函数呢?
答案 0 :(得分:27)
编辑:添加更多示例
您的class
定义(几乎)正确。错误在实例化var Reply = new Reply();
。这会尝试重新定义分配给类名的变量。此外,generator
函数预计会yield
。我详细介绍了一些OP代码来展示工作实例。
class Reply {
//added for test purpose
constructor(...args) {
this.args = args;
}
* getReply(msg) {
for (let arg in this.args) {
let reply = msg + this.args[arg];
//generator should yield something
yield reply;
}
//next call returns (yields) {done:true,value:undefined}
}
* otherFun() {
yield this.getReply('Nice to meet you '); //yields Generator object
yield this.getReply('See you '); //Yes, this can access
//next call yields {done:true, value:undefined}
}
* evenMore() {
yield* this.getReply('I miss you '); //yields generator result(s)
yield* this.getReply('I miss you even more ');
}
}
//now test what we have
const reply = new Reply('Peter', 'James', 'John');
//let and var here are interchangeable because of Global scope
var r = reply.getReply('Hello ');
var msg = r.next(); //{done:false,value:"..."}
while (!msg.done) {
console.log(msg.value);
msg = r.next();
}
var other = reply.otherFun();
var o = other.next(); //{done:false,value:Generator}
while (!o.done) {
let gen = o.value;
msg = gen.next();
while (!msg.done) {
console.log(msg.value);
msg = gen.next();
}
o = other.next();
}
var more = reply.evenMore();
msg = more.next();
while (!msg.done) {
console.log(msg.value);
msg = more.next();
}
//update of 1/12/2019
//more examples
for (let r of reply.getReply('for ')) {
console.log(r);
}
for (let r of reply.evenMore()) {
console.log(r);
}
//note that the following doesn't work because of lack of star (*) inside the generator function
for (let r of reply.otherFun()) {
console.log(r);
}

更新1/12/2019
正如@BugBuddy所提出的for..of
循环看起来更好(但并非在所有情况下都有效)。请参阅代码段中的更新行。
答案 1 :(得分:18)
在Javascript中,如何在类中编写生成器函数?
class A {
* values() {
yield "a value";
yield* [1, 2, 3, 4, 5];
}
}
在语法上是正确的。有用。不客气,现在辞退了。
答案 2 :(得分:-2)
生成器是具有.next()
的函数,用于获取yield
的值,或者您可以yield
生成器函数让它知道它不需要"等待"遇到yield
语句,要求.next
被调用(reply.getReply().next(fn)
)
你的第二段代码几乎是正确的:
class Reply{
*getReply (msg){
//...
return reply;
}
*otherFun(){
this.getReply(); //`this` seem to have no access to `getReply`
}
}
var Reply = new Reply();
Reply.getReply(); //out of class,how can I get access to `getReply`?
首先,在ES6中工作时请使用const
或let
,并且只对类使用大写变体。
您试图用class Reply
语句覆盖var Reply =
语句,这是不可能的,因为Identifier 'Reply'
已经被声明。
您正在寻找的答案如下:
就像你在第一个例子中所做的那样,你应该yield
生成器函数,所以你的看起来应该是这样的:
class Reply{
*getReply (msg){
// yield something here, otherwise you should use a normal function
return reply;
}
*otherFun(){
const reply = yield this.getReply(); // yield the generator so it does what it needs to and doesn't wait for the .next() to be called on it
return `${reply} within class ${this.constructor.name}`;
}
}
const reply = new Reply();
const answer = yield reply.getReply('foo');
// getReply is a generator function, so it needs a `yield` or `.next()` to run beyond the first `yield` in the function