问题
Consider this snippet of code :
function foo(a) {
console.log("Mul =", a);
return a * 2;
};
function * process(start) {
// next() #1
var result = start;
console.log("Pre-processing =", result);
result = yield foo(result);
// next() #2
console.log("Process result 1 =", result);
result = yield foo(result);
// next() #3
console.log("Process result 2 =", result);
result = yield foo(result);
// next() #4
console.log("Process result 3 =", result);
return foo(result);
}
var it = process(1);
console.log("#1");
console.log("Next 1 =", /*#1*/it.next("bar"));
console.log("#2");
console.log("Next 2 =", /*#2*/it.next(3));
console.log("#3");
console.log("Next 3 =", /*#3*/it.next(7));
console.log("#4");
console.log("Next 4 =", /*#4*/it.next(15));
And the output
#1
Pre-processing = 1
Mul = 1
Next 1 = { value: 2, done: false }
#2
Process result 1 = 3
Mul = 3
Next 2 = { value: 6, done: false }
#3
Process result 2 = 7
Mul = 7
Next 3 = { value: 14, done: false }
#4
Process result 3 = 15
Mul = 15
Next 4 = { value: 30, done: true }
Why is the first call to it.next()
skip arguments (in the code above, "bar"
) altogether? Or, in other words, why is the behavior different in subsequent calls? I would've expected calling the generator function would skip arguments, and that the call to next()
would actually initialize the iterator, making the process more coherent, no?
回答1:
In the draft:
After some more research, the answer lies within harmony's draft (see the wiki: http://wiki.ecmascript.org/doku.php?id=harmony:generators#methodnext).
next
is supposed to have no argument. However, it seems calling next
with one argument is just equivalent to call send
with one argument. Here lies the answer. send
is designed to throw an error if called first (no next
prior).
So basically, you should not be able to "initialize" your iterator by passing an argument to next
cause you're not authorized to do so.
In the implementations:
However, this is just the specification. To summarize what's been said as comments, there are at least 2 reasons why you can't pass an argument to your first next
and have to pass it to your generator.
The first one would be the fact that you would need some method to actually get this argument. You cannot do it the same way you'd do it with your next calls let myVar = yield myValue
.
The second one would be that next
only accepts one argument and that is quite limiting, whereas you can pass an infinite amount of arguments to your generator when producing the iterator.
However, this is only what's happening at the moment. Nothing says that the draft or implementations won't change. We could certainly imagine send
accepting any number of arguments (no reason but hey, who knows), and being able to cast it into the generator's arguments. Or whatever.
来源:https://stackoverflow.com/questions/20977379/es6-yield-what-happens-to-the-arguments-of-the-first-call-next