Generator函数
Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。Generator函数是一个状态机,封装了多个内部状态。执行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历Generator函数内部的每一个状态。
For…of循环可以自动遍历Generator函数运行时生成的Iterator对象,且此时不再需要调用next方法。、
下面是一个利用 Generator 函数和for...of循环,实现斐波那契数列的例子。 function* fibonacci() { let [prev, curr] = [0, 1]; for (;;) { yield curr; [prev, curr] = [curr, prev + curr]; } } for (let n of fibonacci()) { if (n > 1000) break; console.log(n); } 从上面代码可见,使用for...of语句时不需要使用next方法。
Next()、throw()、return()、这三个方法本质上是同一件事,可以放在一起理解。它们的作用都是让Generator函数恢复执行,并且使用不同的语句替换yield表达式。
Next()是将yield表达式替换成一个值。
Throw()是将yield表达式替换成一个throw语句。
Return是将yield表达式替换成一个return语句。
Es6提供了yield*表达式,作为解决方法,用来在一个Generator函数里执行另一个Generator函数。
Proxy用于修改某些操作的默认行为,等同于在语言层面作出修改,所以属于一种“元编程”,即对编程语言进行编程。
Proxy可以理解成,在目标对象之前架设一层‘拦截’,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy这个词的原意是代理,用在这里表示由它来‘代理’某些操作,可以译为“代理器”。
var proxy = new Proxy(target, handler);
new Proxy()表示生成一个Proxy实例,target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为。
Reflect对象与Peoxy对象一样,也是ES6为了操作对象而提供的新API。Reflect独享的设计目的有这样几个。
1将Object对象的一些明显属于语言内部的方法,放到Reflect对象上,也就是说,从Reflect对象上可以拿到语言内部的方法。
2修改某些object方法的返回结果,让其变得更合理。
3让object的操作都变成函数行为。
4 Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。这就让Proxy对象可以方便地调用对应的Relfect方法,完成默许行为,作为修改行为的基础。也就是说,不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为。
遍历器(Interator)就是这样一种机制。他是一种接口,为各种不同弄的数据结构提供统一的访问机制。任何数据结构只要部署Interator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
Interator的作用有三个:一是为各种数据结构提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是ES6创造了一种新的遍历命令for…of循环,Interator接口主要供for…of消费。
对于原生部署Interator接口的数据结构,不用自己写遍历器生成函数,for…of循环会自动遍历他们。除此之外,其他数据结构(主要是对象)的Interator接口,都需要自己在Symbol.interator属性上面部署,这样才会被for…of循环遍历。
Export命令
模块功能主要由两个命令构成:export和import。Export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。
编程风格
1:let取代var
2:在let和const之间,建议优先使用const,尤其是在全局环境,不应该设置变量,只应设置常量。Const优于let有几个原因。一个是const可以提醒阅读程序的人,这个变量不应该改变;另一个const比较符合函数式编程思想,运算不改变值,只是新建值,而且这样也有利于将来的分布式运算;最后一个原因是javascript编译器会对const进行优化,所以多使用const,有利于提高程序的运行效率,也就是说let和const的本质区别,其实是编译器内部的处理不同。
3:静态字符串一律使用单引号或反引号,不使用双引号。动态字符串使用反引号。
4:使用数组成员对变量进行赋值时,优先使用解构赋值。函数的参数如果是对象的成员,优先使用结构赋值。如果函数返回多个值,优先使用对象的结构赋值,而不是数组的解构赋值。这样便于以后添加返回值,以及更改返回值的顺序。
5:单行定义的对象,最后一个成员不以逗号结尾。多行定义的对象,最后一个对象以逗号结尾。对象尽量静态化,一旦定义,就不得随意添加新的属性。
6:使用扩展运算符(…)拷贝数组。使用Array.from方法,将类似数组的对象转为数组。
7:立即执行函数可以写成箭头函数的形式。那些使用匿名函数当做参数的场合,尽量用箭头函数代替。因为这样更简洁,而且绑定了this。
8:注意区分Object和Map,只有模拟现实世界的实体对象时,才使用Object。如果只需要key:value的数据结构,使用Map结构。因为map有内建的遍历机制。