14. iterator 和 for...of 循环
* 不同的数据结构通过 for...of 统一的这种形式来达到读取不同数据结构的目标
* 但是背后的iterator接口是不一样的
iterator
{ //循环数组 let arr = ["hello", "world"]; let map = arr[Symbol.iterator](); console.log(map.next()); //{value: "hello", done: false} console.log(map.next()); //{value: "world", done: false} console.log(map.next()); //{value: undefined, done: true} }
{ //自定义iterator 接口 let obj = { start: [1, 3, 2], end: [7, 9, 8], [Symbol.iterator]() { let self = this; let index = 0; let arr = self.start.concat(self.end); let len = arr.length; return { next() { if (index < len) { return { value: arr[index++], done: false }; } else { return { value: arr[index++], done: true }; } } }; } }; for (let key of obj) { console.log(key); //1 3 2 7 9 8 } }
for...of
{ let arr = ["hello", "world"]; for (let item of arr) { console.log("item", item); // hello // world } }
15. Generator
异步编程的解决方案
基本定义
{ // 基本定义 let tell = function*() { yield "a"; yield "b"; return "c"; }; let k = tell(); // 调用next()时 会去执行第一个yield,保证了函数体内异步操作的过程 console.log(k.next()); console.log(k.next()); console.log(k.next()); console.log(k.next()); // {value: "a", done: false} // {value: "b", done: false} // {value: "c", done: true} // {value: undefined, done: true} }
generator 和 iterator 的关系
{ let obj = {}; obj[Symbol.iterator] = function*() { yield 1; yield 2; yield 3; }; for (let value of obj) { console.log(value); //1 //2 //3 } }
状态机
{ //状态机 let state = function*() { while (1) { yield "A"; yield "B"; yield "C"; } }; let status = state(); console.log(status.next()); console.log(status.next()); console.log(status.next()); console.log(status.next()); console.log(status.next()); // {value: "A", done: false} // {value: "B", done: false} // {value: "C", done: false} // {value: "A", done: false} // {value: "B", done: false} } // async await // { // let state = async function() { // while (1) { // await "A"; // await "B"; // await "C"; // } // }; // let status = state(); // console.log(status.next()); // console.log(status.next()); // console.log(status.next()); // console.log(status.next()); // console.log(status.next()); // }
实例
{ //抽奖 let draw = function(count) { //具体抽奖逻辑 console.log(`剩余${count}次`); }; //计算次 let residue = function*(count) { while (count > 0) { count--; yield draw(count); } }; let star = residue(5); let btn = document.createElement("button"); btn.id = "start"; btn.textContent = "抽奖"; document.body.appendChild(btn); document.getElementById("start").addEventListener( "click", function() { star.next(); }, false ); } { //长轮询 let ajax = function*() { yield new Promise(function(resolve, reject) { setTimeout(() => { resolve({ code: 0 }); }, 200); }); }; let pull = function() { let generator = ajax(); let step = generator.next(); step.value.then(function(d) { if (d.code != 0) { setTimeout(() => { console.info("wait"); pull(); }, 1000); } else { console.info(d); } }); }; pull(); //{code: 0} }
16. Decorator - 修饰器
一个用来修改类的行为的 函数,可以理解为扩展类的功能
{ let readonly = function(target, name, descriptor) { descriptor.writable = false; return descriptor; }; class Test { //在这里加了修饰器 不允许重新赋值 @readonly Time() { return "2019-07-11"; } } let test = new Test(); console.log(test.Time()); //2019-07-11 }
{ let typename = function(target, name, descriptor) { target.myname = "hello"; }; @typename class Test {} //类修饰符 console.log(Test.myname); //hello }
{ let log = type => { return function(target, name, descriptor) { let src_method = descriptor.value; descriptor.value = (...arg) => { src_method.apply(target, arg); console.info(`log ${type}`); }; }; }; class AD { @log("show") show() { console.info("ad is show"); } @log("click") click() { console.info("ad is click"); } } let ad = new AD(); ad.show(); ad.click(); }
17. 模块化
方法一
导出
/* 方法一 export let A = 123; export function test() { console.log("test"); } export class Hello { test() { console.log("class"); } } */
引入
// import { A, test, Hello } from "./class/lesson17"; // import { A } from "./class/lesson17"; // import * as lesson from "./class/lesson17";
方法二(推荐)
导出
let A = 123; let test = function() { console.log("test"); }; class Hello { test() { console.log("class"); } } export default { A, test, Hello };
引入
import lesson17 from "./class/lesson17";
使用
// console.log(A, test, Hello); // console.log(A); // console.log(lesson.A); // console.log(lesson.test()); console.log(lesson17.A);