es6之Generator
1.Generator函数其实是一个封装了多个内部状态的状态机,执行它会返回一个遍历器对象,然后可以依次遍历Generator中的每一个状态,也就是分段执行,yield是暂停执行的标记,next恢复执行。
2.yield:
- 一个函数里面,return只能执行一遍,yield可以执行多次;
- Generator函数可以不用yield,这时就是一个简单的暂缓执行函数;
- yield只能用在Generator函数里;
- yield如果用在一个表达式里,必须放在圆括号里
function* foo() { console.log('hello' + (yield)); console.log('hello' + (yield 'world')); }
- yield用于函数参数或放在赋值表达式的右边,可以不加括号
function* demo() { foo(yield 'a', yield 'b'); let input = yield; }
3.可以把Generator函数赋值给对象的Symbol.iterator属性,从而使对象具有Iterator接口
var obj = {}; obj[Symbol.iterator] = function* (){ yield 1; yield 2; }; [...obj] // [1,2]
4.next方法的参数会被当做上一个yield的返回值,这样就可以在函数运行期间向内部传值。
5.for...of会自动遍历Generator函数生成的Iterator对象,不需要调用next方法。
// 实现Fibonacci数列 function* fib() { let [prev, curr] = [0, 1]; for (;;) { [prev, curr] = [curr, prev + curr]; yield curr; } } for (let n of fib()) { if (n > 1000) break; console.log(n); }
6.遍历器对象的throw方法。
7.遍历器对象的return方法可以返回给定的值且终结遍历。
8.yield* 表达式用来在一个Generator函数里调用另一个Generator函数,而后面这个函数其实就是for...of的一种简写;
- yield* 后面如果跟着数组,则会遍历该数组;
- yield* 后面如果跟着字符串,也会遍历字符串;
- 如果后面的Generator函数有return语句,那么就可以像这个函数返回数据
function *foo() { yield 2; return "foo"; } function *bar() { yield 1; var v = yield *foo(); console.log( "v: " + v ); yield 3; } var it = bar(); it.next() // {value: 1, done: false} it.next() // {value: 2, done: false} it.next() // "v: foo" // {value: 3, done: false} it.next() // {value: undefined, done: true}
9.作为属性的Generator: let obj = { * foo(){}};
10.Generator函数返回的遍历器对象是函数的实例,也继承了函数的prototype上的方法;
// 使用this function* F() { this.a = 1; yield this.b = 2; } var f = F.call(F.prototype); f.next(); // Object {value: 2, done: false} f.next(); // Object {value: undefined, done: true} f.a // 1 f.b // 2
11.Generator函数的应用:
- 异步操作可以用同步写法;
- 控制流管理;
- 部署Iterator接口;
12.协程:多个线程互相协作,完成异步任务;Generator函数就是协程在es6的实现,其特点是交出函数的执行权。
13.Thunk函数其实就是传名调用,将参数放到一个临时函数中,用来替换某个表达式传入函数体。
function f(m) { return m * 2; } f(x + 5); // 等同于 var thunk = function () { return x + 5; }; function f(thunk) { return thunk() * 2; }
在js中,js是传值调用,Thunk 函数替换的不是表达式,而是多参数函数,将其替换成一个只接受回调函数作为参数的单参数函数。Thunk 函数是自动执行 Generator 函数的一种方法。
// 正常版本的readFile(多参数版本) fs.readFile(file, callback); // Thunk版本的readFile(单参数版本) var Thunk = function (file) { return function (callback) { return fs.readFile(file, callback); }; }; var readFileThunk = Thunk(file); readFileThunk(callback);