多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
#### 迭代器 ``` var a = [1, 2, 3]; var it = a[Symbol.iterator](); it.next(); //{value: 1, done: false} it.next(); //{value: 2, done: false} it.next(); //{value: 3, done: false} it.next(); //{value: undefined, done: true} //你可以把[1, 2, 3]看成是[yield 1, yield 2, yield 3],这样你就明白为什么value为3时done还是false了 var str = "hello world"; var _it = str[Symbol.iterator](); _it.next(); //{value: h, done: false}; ... //str并不能迭代,而是js帮你通过封箱技术封装成了String对象 //Array String Generator Collection/TypedArray 允许迭代 ``` 迭代器如果throw了一个error但是没有在上下文中捕获,那么会导致整个迭代器终止 迭代器本身是iterable,那它可以直接用于for of循环 ``` //你可以通过为迭代器提供一个Symbol.iterator并返回自身来使其成为iterable var it = { [Symbol.iterator]() {return this;}, next() { return { value: this.i++, done: this.i > 5 ? true : false }; }, i: 0 } for(var i of it) { console.log(i); } //0 1 2 3 4 ``` 还记得之前的例子吗?[1, 2, 3]迭代后value为3的done并不是true,因为 ``` for(var val, res, it = a[Symbol.iterator](); (res = it.next()) && !res.done) ``` 的判断条件一旦done为true,此时循环就结束了,最后一个值将无法获取,因此es6规定[1, 2, 3]遍历完后的下一个next的done才是true 迭代器消耗 除了for of外,解构也可以消耗迭代器 ``` var a = [1, 2, 3, 4, 5]; var it = a[Symbol.iterator](); var [x, y] = it; var [z, ...w] = it; //一样的,再调一次nextdone才是true it.next(); //{value: undefined, done: true} x; //1 y; //2 z; //3 w; //[4, 5] ``` #### 生成器 ``` yield 3 //合法 a = 2 * (yield) //合法 a = 2 * yield 3 //不合法 a = 2 * (yield 3) //合法 ``` yield优先级很低很低,仅次于spread运算符和... ``` yield 2 + 3 相当于yield (2 + 3) //因此,用() (yield 2) + 3 ``` ``` function *foo() { yield 1; yield 2; yield 3; return 4; } function *bar() { var x = yield *foo(); console.log("x:", x); } for(var i of bar()){ console.log(i) } //1 2 3 //x: 4 ``` 提前完成 ``` function *foo() { yield 1; yield 2; yield 3 } var it = foo(); it.next(); //{value: 1, done: false} it.return(4); //{value: 4, done: true} it.next(); //{value: undefined, done: true} it.next(5); //{value: undefined, done: true} //it.throw如果在迭代器内部没有做出异常处理的化,迭代器一样会提前结束 function *foo() { //没有做异常处理try catch yield 1; yield 2; yield 3; } var it = foo(); it.next(); //{value: 1, done: false} try { it.throw(4); //{value: 4, done: true} } catch(err) { console.log(err); } it.next(); //{value: undefined, done: true} ``` ``` function *foo() { //做了处理 try { yield 1; } catch(err) {console.log(err)} yield 2; yield 3; } var it = foo(); it.next(); //{value: 1, done: false} it.throw(4);//4 //{value: 2, done: false} ``` foo()每次都会创建一个新的迭代器,而不是多个迭代器公用一个foo() #### 模块 ``` var foo = 2; export foo; //导出2 export {foo}; //导出{foo: 2} export {foo as bar}; //导出{bar: 2} 相当于模块重命名 export {foo as default}; //相当于export default foo; export {a: {}, b: {}}; //每个js文件可以有多个导出,但只能有一个默认导出 import {foo} from ...; import {bar} from ...; import foo from ...; import {a, b} from ...;或import * from ...;或import * as o from ...; //import也可以重命名 import {foo as _foo} from ...; ``` 所有导入的模块应当是只读的,否则用户很有可能修改了模块本身,这是不行的 ``` import * as foo from ...; foo = {}; //TypeError foo.a = 1; //TypeError ``` #### 类 ``` class Foo { constructor(a, b) { this.x = a; this.y = b; } gimmeXY() { return this.x * this.y } } //类似于 function Foo(a, b) { this.x = a; this.y = b; } Foo.prototype.gimmeXY = function() { return this.x * this.y } ``` ``` class Bar extends Foo { constructor(a, b, c) { super(a, b); this.z = c; } gimmeXYZ() { super.gimmeXY() * this.z; } } var b = new Bar(5, 15, 25); b.x; //5 b.y; //15 b.z; //25 b.gimmeXYZ(); //1875 //A extends B相当于把A的prototype的[[Prototype]]链接到B的prototype中 //A.prototype = Object.create(B.prototype) ``` ``` class ParentA { constructor() { this.id = "a"; } foo() { console.log("ParentA:", this.id); } } class ParentB { constructor() { this.id = "b"; } foo() { console.log("ParentB:", this.id); } } class ChildA extends ParentA { foo() { super.foo(); console.log("ChildA:", this.id); } } class ChildB extends ParentB { foo() { super.foo(); console.log("ChildB:", this.id); } } var a = new ChildA(); a.foo(); //ParentA: a //ChildA: a var b = new ChildB(); b.foo(); //ParentB: b //ChildB: b b.foo.call(a); //ParentB: a //ChildB: a ``` static指定的属性是直接创建在函数上的而不是函数的原型上 ``` class Bar { static net() { console.log(".net") } } Bar.net(); //.net var b = new Bar(); b.net; //undefined //这是当然的了,因为 function Bar() { net() { console.log(".net") } } var b = new Bar(); b.net; //undefined ``` new.target(元属性) ``` //new.target总是指向new实际上直接调用的构造器 class Foo { constructor() { console.log("Foo:", new.target.name) } } class Bar extends Foo { constructor() { super(); console.log("Bar:", new.target.name)} baz() { console.log("baz:", new.target.name) } } var a = new Foo(); //Foo: Foo var b= new Bar(); //Foo: Bar //Bar: Bar b.baz(); //baz: undefined ```