1 function* generator() { 2 yield ‘Owen‘; 3 yield 18; 4 return ‘end‘; 5 } 6 7 8 //调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象 Iterator 9 let person = generator(); 10 11 12 person.next() //{value:‘Owen‘,done:false} 13 person.next() //{value:18,done:false} 14 person.next() //{value:‘end‘,done:true} 15 person.next() //{value:undefined,done:true} 16 person.next() //{value:undefined,done:true}
- 调用 `next` 遇到 `yield`表达式 暂停执行函数后面的操作,并且 <label> 紧跟 `yield` 后面的表达式的值</label>作为返回对象 `value` 属性的值。
function* g(){ yield 1 + 2 } let num = g() num //g {<suspended>} num.next() //{value:3,done:false} num.next() //{value:undefined,done:true}
let iter = {}; iter[Symbol.iterator] = function* (){ yield 1; yield 2; yield 3; } [...iter] //[1, 2, 3]
1 let g = fn(); 2 g.next() //{value:0,done:false} 3 g.next() //{value:1,done:false} 4 g.next() //{value:2,done:false} 5 g.next(1) //{value:0,done:false} 6 7 function* fn (){ 8 for (let i = 0; true; i++){ 9 let reset = yield i; 10 if(reset) i = -1; 11 } 12 } 13 function* dataConsumer() { 14 console.log(‘Started‘); 15 console.log(`1. ${yield}`); 16 console.log(`2. ${yield}`); 17 return ‘result‘; 18 } 19 let genObj = dataConsumer(); 20 genObj.next(); 21 // Started 22 //{value: "undefined", done: fales} 23 genObj.next(‘a‘) 24 //1. a 25 //{value: "undefined", done: fales} 26 genObj.next(‘b‘) 27 //2. b 28 //{value: "result", done: true}
1 function* fn(){ 2 yield 1; 3 yield 2; 4 yield 3; 5 yield 4; 6 yield 5; 7 return 6; 8 } 9 10 for (let i of fn()){ 11 console.log(i); 12 //1 2 3 4 5 undefined 13 } 14 15 16 //斐波那契数列 17 18 function* fibonacci() { 19 let [prev, curr] = [0, 1]; 20 for (;;) { 21 yield curr; 22 [prev,curr] = [curr, prev + curr]; 23 } 24 } 25 26 for (let f of fibonacci()) { 27 if (f > 1000) break; 28 console.log(f) 29 } 30 31 //遍历任意对象方法 32 33 function* objectEntries(obj) { 34 let propKeys = Reflect.ownKeys(obj); 35 36 for (let key of propKeys){ 37 yield [key,obj[key]]; 38 } 39 } 40 41 let person = {name:‘Owen‘, age:18}; 42 43 for (let [key,value] of Object.entries(person)){ 44 console.log(key,value); 45 //name Owen 46 // age 18 47 } 48 49 for (let [key,value] of objectEntries(person)){ 50 console.log(key,value); 51 //name Owen 52 // age 18 53 } 54 //或者 55 56 person[Symbol.interator] = objectEntries 57 58 for (let [key,value] of person){ 59 console.log(key,value); 60 //name Owen 61 // age 18 62 }
function* g() { try { yield; } catch (e) { console.log(‘内部1‘,e ) }; try { yield; } catch (e) { console.log(‘内部2‘,e) }; } let t = g(); t.next(); //{value: undefined, done: false} try{ t.throw(‘a‘); t.throw(‘b‘); t.throw(‘c‘); } catch(e){ console.log(‘外部‘,e) } //内部1 a //内部2 b //外部 c
Generator return
function* g(){ yield 1; yield 2; } let ge = g(); ge.next(); // { value: 1, done: false } ge.return(‘Owen‘); // { value:"Owen", done: true } ge.next() // { value: undefined, done: true } // try...finally function* numbers () { yield 1; try { yield 2; yield 3; } finally { yield 4; yield 5; } yield 6; } var nun = numbers(); nun.next() // { value: 1, done: false } nun.next() // { value: 2, done: false } nun.return(7) // { value: 4, done: false } nun.next() // { value: 5, done: false } nun.next() // { value: 7, done: true }
yield*
//默认 function* f(){ yield 1; yield 2; } function* g(){ yield ‘x‘; f(); yield ‘y‘; } for(let key of g()){ console.log(key) //"x" "y" } //yield* function* y(){ yield ‘x‘; yield* f(); yield ‘y‘; } for (let k of y()) { console.log(k); // "x" "y" 1 2 } //无 return function* concat(iter1, iter2) { yield* iter1; yield* iter2; } // 等同于 function* concat(iter1, iter2) { for (var value of iter1) { yield value; } for (var value of iter2) { yield value; } } // yield* array 如果去掉 * 会返回整个数组 //任何数据结构只要有 Iterator 接口,就可以被yield*遍历。 function* gen(){ yield* ["a", "b", "c"]; } var g = gen(); g.next() //{value: "a", done: false} g.next() //{value: "b", done: false} g.next() //{value: "c", done: false} g.next() //{value: undefined, done: true} //取出嵌套数组的所有成员 function* iterTree(tree) { if (Array.isArray(tree)){ for (let arr of tree) { yield* iterTree(arr) } }else{ yield tree } } const tree = [1,[2,3],[4,[5,6],7],8]; for (let v of iterTree(tree)){ console.log(v) } //1 2 3 4 5 6 7 8 [...iterTree(tree)] //[1, 2, 3, 4, 5, 6, 7, 8] //遍历完全二叉树 // 下面是二叉树的构造函数, // 三个参数分别是左树、当前节点和右树 function Tree(left, label, right) { this.left = left; this.label = label; this.right = right; } // 下面是中序(inorder)遍历函数。 // 由于返回的是一个遍历器,所以要用generator函数。 // 函数体内采用递归算法,所以左树和右树要用yield*遍历 function* inorder(t) { if (t) { yield* inorder(t.left); yield t.label; yield* inorder(t.right); } } // 下面生成二叉树 function make(array) { // 判断是否为叶节点 if (array.length == 1) return new Tree(null, array[0], null); return new Tree(make(array[0]), array[1], make(array[2])); } let tree = make([[[‘a‘], ‘b‘, [‘c‘]], ‘d‘, [[‘e‘], ‘f‘, [‘g‘]]]); // 遍历二叉树 var result = []; for (let node of inorder(tree)) { result.push(node); } result // [‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘, ‘f‘, ‘g‘]
let obj = { * generator(){ } } //or let obj1 = { generator :function* () { } } ``` ### Generator 函数的this > Generator 函数不能和 new 一起使用 > <label>函数总返回一个遍历器,并且它指向 函数实例,同时继承 函数原型对象上的方法</label> ```javascript function* g() { this.say = function(){ return 18 }; } g.prototype.say = function () { return "Owen" } let obj =g() //g {<suspended>} obj instanceof g //true obj.say() //"Owen" obj.next() //{value: undefined, done: true} obj.say() //"Owen" //因为 next 返回的是遍历器对象而不是 this 对象,所以不会返回 18 //通过call 绑定this function* Gen(){ this.age = 18; yield this.name = "Owen"; } let obj = Gen.call(Gen.prototype); obj.next() obj.age // 18 obj.next(); obj.name //"Owen" // 使用 new 的变通方法 function G(){ return Gen.call(Gen.prototype) } let obj1 = new G(); obj1.next() obj1.age // 18 obj1.next(); obj1.name //"Owen"
$.ajax({ url:‘url‘, success:function(res){ console.log(res) } })
el.addEventListener(event,function(){ },boolean); //IE8 以下 el.attachEvent(event,function(){}) //事件代理委托 var parent = document.getElementById(‘parent‘); parent.addEventListener(‘click‘,showColor,false); function showColor(e){ var son = e.target; if(son.nodeName.toLowerCase() === ‘li‘){ console.log(‘The color is ‘ + son.innerHTML); } }
//实现一个简单的发布订阅 /* 订阅一个事件,发布对应事件并且执行方法 需要先有代理主题 message proxy 然后订阅者去订阅 然后发布者发布消息执行方法 */ function PubSub () {}; // message proxy PubSub.prototype.message = {}; // publish PubSub.prototype.pub = function () { // Turn arguments into real array let args = [].slice.call(arguments,0); let event = args.shift(); if(!this.message[event]) return this; let list = this.message[event]; for (let item of list) { item.apply(this,args); } return this; } // subscribe PubSub.prototype.sub = function (event,callback){ if( !this.message[event]) { this.message[event] = []; } this.message[event].push(callback); return this; } // unsubscribe PubSub.prototype.unsub = function (event) { if (!this.message[event]) return this; this.message[event] = null; }
// read I/O let readFile = require(‘fs-readfile-promise‘); readFile(fileA) .then( (data) => console.log(data.toString())) .then( () => readFile(fileB)) .then( (data) => console.log(data.toString())) .catch((err) => console.log(err));
//example function* async () { //... do something let file = yield readFile(fileA); //... do something } //异步操作需要暂停的地方,都用yield语句注明
协程代码的写法非常像同步操作,Generator 函数最大优点是可以交出函数执行权
function* async (num) { let n; try{ n = yield ++num; }catch(err){ console.log(err) } return n } let g = async(1); g.next() g.throw(‘error‘);
let fetch = require(‘node-fetch‘); let g = gen(); let result = g.next(); result.value.then((data) => data.json()) .then((data) => g.next(data) ); function* gen() { let url = ‘/index.json‘; let result = yield fetch(url); }
//传值 var x = 3; function fn (x,b) { return x * 3 }; fn(x + 1) // 4 * 3 //传名 fn(x + 1) // (x + 1) * 3 //等同于 var thunk = function (){ return x + 1} fn (thunk) // thunk() * 3
原文:https://www.cnblogs.com/gaoguowen/p/10874807.html