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` 屬性的值。javascript
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 returnjava
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*node
//默認 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 函數最大優勢是能夠交出函數執行權es6
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