ES6常用
ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准。
1. let 和 const
1 {
2 var a=5;
3 let b=10;
4 }
5 console.log(a);
6 console.log(b);
控制台就是这样输出:
也就是说,var声明的变量由于不存在块级作用域所以可以在全局环境中调用,而let声明的变量由于存在块级作用域所以不能在全局环境中调用。
再来看一个经典例子(闭包):
1 var a=[];
2 //执行for循环
3 for(var i=0;i<10;i++){
4 a[i]=function(){ //因为这个是定义,并没有调用方法,不会执行
5 console.log(i);
6 };
7 }
8 //for循环之后,此时 i = 10;再次执行a[6]();因为 i 一直被引用,所以不会回收,进入到 a[i] 的方法里面, 打印的是 i ,也就是10
9 a[6](); //输出10
如果使用 let
1 var a=[];
2 for(let i=0;i<10;i++){
3 a[i]=function(){
4 console.log(i);
5 };
6 }
7 a[6](); //打印6
a[6]函数(闭包)这个执行环境中,它会首先寻找该执行环境中是否存在 i,没有找到,因为 i 是块级作用域,就沿着作用域链继续向上到了其所在的代码块执行环境,找到了i=6,于是输出了6,即a[6]();的结果为6。这时,闭包被调用,所以整个代码块中的变量i和函数a[6]()被销毁。
const 是定义常量:const a = 14; 此后变量 a 的值无法更改覆盖。
2. 字符串拼接
1 //传统字符串拼接
2 var s1 = '生物膜系统组装又拆分,变幻莫测;';
3 var s2 = '你的好多细胞在分裂,';
4 var str = '孩子们:请听我说!'+s2+'有丝,减数,哪管白天和黑夜。'+
5 '染色体,细胞核时隐时现,'+s1+'核糖体在mRNA上穿梭忙碌,'+'几千种酶各司其职,将活化能狠狠打折。';
6 console.log(str);
7
8 // 字符模板的写法
9 var s1 = '染色体,细胞核时隐时现,';
10 var s2 = '你的好多细胞在分裂,';
11 var str = `孩子们:请听我说!${s2}有丝,减数,哪管白天和黑夜。${s1}生物膜系统组装又拆分,变幻莫测;核糖体在mRNA上穿梭忙碌,几千种酶各司其职,将活化能狠狠打折。`;
12 console.log(str);
es6使用 ` ` 包裹字符串,即使断开,也可以用这个符号包裹起来合并成一个字符串。
3. 解构赋值
1 // 以前我们给变量赋值,只能直接指定值
2 var a = 1;
3 var b = 2;
4 var c = 3;
5 console.log(a,b,c); // 1 2 3
6
7 // 现在用解构赋值的写法就变得简单了,只要模式匹配上了就行了,如下
8 // 注意数组是有顺序的
9 var [a,b,c] = [11,22,33];
10 console.log(a,b,c); // 11 22 33
11
12 var [b,a,c] = [11,22,33];
13 console.log(a,b,c); // 22 11 33
14
15 // 当然解构赋值还有嵌套比较复杂的写法,如下
16 let [foo,[[bar],[baz]]] = [111,[[222],[333]]];
17 console.log(foo,bar,baz); // 111 222 333
18
19 let [head,...foot] = [1,2,3,4];
20 console.log(head,foot); // 1 [2,3,4]
21
22 // 如果解构不成功,变量的值就等于undefined,如下
23 var [bar3,foo3] = [1000];
24 console.log(bar3,foo3); // 1000 undefined
25
26 // 另一种情况是不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功
27 let [x,y] = [10000,20000,30000];
28 console.log(x,y); // 10000 20000
29
30 // 默认值可以引用解构赋值的其他变量,但该变量必须已经声明
31 let [a=1,b=a] = [2,3];
32 console.log(a,b); // 2 3
33
34 // 对象的解构也可以指定默认值
35 var {x,y=5} = {x:1};
36 console.log(x,y); // 1 5
37
38 //对象的解构赋值解构不仅可以用于数组,还可以用于对象(json)
39 //对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;
40 //而对象的属性没有次序,变量必须与属性同名,才能取到正确的值
41 var {a,b} = {a:'apple',b:'banana'};
42 console.log(a,b); // apple banana
43 var {b,a} = {a:'apple',b:'banana'};
44 console.log(a,b); // apple banana
45
46 // 如果变量名与属性名不一致,必须写成下面这样
47 let obj = {first:'hello',last:'world'};
48 // first ---> f,那么此时f就是first,而不是undefined了,有点类似别名的概念
49 let {first:f,last} = obj;
50 console.log(f,last); // hello world
51
52 //1.也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。 真正被赋值的是后者,而不是前者
53 //2.v是匹配的模式,n才是变量。真正被赋值的是变量n,而不是模式v。
54 //注意,采用这种写法时,变量的声明和赋值是一体的
55 // v ---> n,那么此时n就是vue,而不是undefined了
56 var {v:n} = {v:'vue',r:'react'};
57 console.log(n); // vue
58 console.log(v); // Uncaught ReferenceError: v is not defined
59 console.log(r); // Uncaught ReferenceError: r is not defined
4. 复制数组
1 // 数组的浅拷贝,引用之间的拷贝,没有实现数组的真正复制
2 var arr1 = [1, 2, 3];
3 var arr2 = arr1;
4 arr2.push(4);
5 console.log(arr1, arr2); //[1, 2, 3, 4] [1, 2, 3, 4]
6
7 // 复制数组深拷贝,传统做法
8 var arr1 = [1,2,3];
9 var arr2 = [];
10 //通过for循环遍历之后将arr1数组的每一项赋值给arr2数组的每一项, 就实现了数组的深拷贝,这时候我再去操作arr2的数组的时候,arr1就不会受影响了
11 for(var i=0;i<arr1.length;i++){
12 arr2[i] = arr1[i];
13 }
14 // 数组尾部添加
15 arr2.push(4);
16 console.log(arr1,arr2);
17
18 // ES6实现的数组的深拷贝方法1
19 var arr1 = [1,2,3];
20 var arr2 = Array.from(arr1);
21 // 数组尾部添加
22 arr2.push(100);
23 console.log(arr1,arr2); // [1, 2, 3] [1, 2, 3, 100]
24
25 // ES6实现的数组的深拷贝方法2
26 var arr1 = [1,2,3];
27 // 超引用拷贝数组
28 var arr2 = [...arr1];
29 // 数组尾部添加
30 arr2.push(1000);
31 console.log(arr1,arr2); // [1, 2, 3] [1, 2, 3, 1000]
32
33 function show(...args){
34 // 此时这个形式参数就是一个数组,我们可以直接push东西进来,如下
35 args.push(5);
36 console.log(args);
37 }
38 // 调用
39 show(1,2,3,4); // [1, 2, 3, 4, 5]
5. 增加了Map对象,倾向于后台
1 var map = new Map();
2 // 设置
3 // map.set(name,value);
4 map.set('a','apple');
5 map.set('b','banana');
6 // 获取
7 // map.get(name);
8 console.log(map.get('a') + ' ' + map.get('b'));
9 // 删除之前map对象
10 console.log(map);
11 // 删除
12 // map.delete(name);
13 map.delete('a');
14 // 删除之后map对象
15 console.log(map);
16
17 // 注意for..in是不能循环map对象的,不报错也无任何反应,所以下一代码无任何输出,稍微注意下
18 for(var name in map){
19 console.log(name);
20 }
21
22 // 实体 map对象的循环输出
23 for(var name of map){
24 //循环出来的结果就是:a,apple b,banana 循环key,value
25 console.log(name);
26 }
27
28 //循环出来的结果就是: a,apple b,banana 循环key,value
29 for(var [key,value] of map.entries()){
30 console.log(key,value);
31 }
32
33 //只循环key
34 for(var key of map.keys()){
35 console.log(key);
36 }
37
38 //只循环value
39 for(var val of map.values()){
40 console.log(val);
41 }
6. for-of循环 ,上一例子也说到了for-of循环map对象输出
1 //for of一个arr对象
2 var arr = ['红楼梦','西游记','三国演义','水浒传','火影'];
3 //只循环key 0 1 2 3 4 输出key值,也就是下标索引
4 for(var key of arr.keys()){
5 console.log(key);
6 }
7 //只循环value,注意数组是没有.values() 直接 var value of arr ,输出 红楼梦,西游记,三国演义,水浒传,火影
8 for(var value of arr){
9 console.log(value);
10 }
11 //循环key,value
12 for(var [key,value] of arr.entries()){
13 console.log(key,value);
14 }
15
16 //for in循环与for of循环的区别
17 var arr = ['apple','banana','orange','pear'];
18 for(var i in arr){
19 // i打印出来的就是arr数组对应的索引
20 // 0 1 2 3
21 console.log(i);
22 }
23 for(var i of arr){
24 // i值打印出来的就是我们想要的数组具体的值
25 // apple banana orange pear
26 console.log(i);
27 }
28
29 //for of不能循环json
30 var json = {'a':'apple','b':'banana','c':'orange','d':'pear'};
31 for(var name in json){
32 // a b c d
33 console.log(name);
34 // apple
35 console.log(json.a);
36 // pear
37 console.log(json['d']);
38 }
39 // 注意for..of可以循环arr,但是不可以循环json,会报错,特别注意下
40 for(var name of json){
41 Uncaught TypeError: undefined is not a function
42 console.log(json);
43 }
7. 箭头函数:引入箭头函数有两个方面的作用:更简短的函数并且不绑定this
。
箭头函数表达式的语法比函数表达式更短,并且不绑定自己的this,arguments,super或 new.target。这些函数表达式最适合用于非方法函数,并且它们不能用作构造函数,不能使用new。
箭头函数的写法 function(){ } 变成 ()=>{ }
1 var a = ()=>{
2 return 1;
3 }
等价于
1 function a(){
2 return 1;
3 }
如果函数体只有一条语句,可以这样写:
1 var fun = ()=>Math.random()*10
2 console.log(fun());
这样子调用这个箭头函数就会直接返回这条语句的值
箭头函数不绑定arguments,取而代之用rest参数…解决
1 function A(a){
2 console.log(arguments); //[object Arguments] [1, 2, 3]
3 }
4
5 var B = (b)=>{
6 console.log(arguments); //错误:ReferenceError: arguments is not defined
7 }
8
9 var C = (...c)=>{ //...c即为rest参数
10 console.log(c); //[3, 1, 2]
11 }
12 A(1,2,3);
13 B(2,1,3);
14 C(3,1,2);
箭头函数会捕获其所在上下文的 this 值,作为自己的 this 值
1 var obj = {
2 a: 10,
3 b: function(){
4 console.log(this.a); //输出10
5 },
6 c: function() {
7 return ()=>{
8 console.log(this.a); //输出10,捕获了上面obj的this作为自己的this
9 }
10 }
11 }
12 obj.b();
13 obj.c()();
所谓箭头函数的 this 捕获的是所在的上下文,比如下面这个例子:b
是一个箭头函数,然后它的 this
是指向window
,这是为什么呢,因为箭头函数捕获的是obj{}
这个对象的环境,然后这个环境的this
指向的是window
,就相当于上一条的例子:在c
方法里面return
的那个箭头函数捕获的是c:function(){}
这个环境的this
,而这个环境的this
是obj
1 var obj = {
2 a: 10,
3 b: () => {
4 console.log(this.a); //undefined
5 console.log(this); //window
6 },
7 c: function() {
8 console.log(this.a); //10
9 console.log(this); //obj{...}
10 }
11 }
12 obj.b();
13 obj.c();
对于函数的this
指向问题:
- 箭头函数的
this
永远指向其上下文的this
,任何方法都改变不了其指向,如call(), bind(), apply()
- 普通函数的
this
指向调用它的那个对象
8. 对象的简洁语法
1 //传统对象_单体模式写法 key-value模式
2 var person = {
3 name:'krry',
4 age:21,
5 showName:function(){
6 return this.name;
7 },
8 showAge:function(){
9 return this.age;
10 }
11 };
12 // 调用
13 console.log(person.showName()); // krry
14 console.log(person.showAge()); // 21
15
16 //ES6_单体模式写法 不需要写key
17 var name = 'krry';
18 var age = 21;
19 var person = {
20 name,
21 age,
22 showName(){
23 return this.name;
24 },
25 showAge(){
26 return this.age;
27 }
28 };
29 // 调用
30 console.log(person.showName()); // krry
31 console.log(person.showAge()); // 21
9. 类和继承(class和extends)
1. 传统面向对象的写法:
1 function Person(name,age){ // 类、构造函数
2 this.name = name;
3 this.age = age;
4 }
5 Person.prototype.showName = function(){
6 return this.name;
7 };
8 Person.prototype.showAge = function(){
9 return this.age;
10 };
11 var p1 = new Person('allen',28);
12 var p2 = new Person('xiaoxiaoyou',101);
13 console.log(p1.showName()); // allen
14 console.log(p2.showAge()); // 101
15 console.log(p1.showName == p2.showName); //true 注意不是调用方法,没有括号,所以才true
16 console.log(p1.constructor == Person); // true 构造方法相等
2. ES6面向对象写法:
1 class Person{
2 // 构造器
3 constructor(name,age){
4 this.name = name;
5 this.age = age;
6 }
7 showName(){
8 return this.name;
9 }
10 showAge(){
11 return this.age;
12 }
13 }
14 var p1 = new Person('aaa',18);
15 var p2 = new Person('bbb',20);
16 console.log(p1.name); // aaa
17 console.log(p1.showName()); // aaa
18 console.log(p2.showAge()); // 20
19 console.log(p1.showAge == p2.showAge); // true
20 console.log(p1.constructor == Person); // true
3. 面向对象给class赋值默认值:
1 class Person{
2 // 构造器
3 constructor(name='default',age=0){
4 this.name = name;
5 this.age = age;
6 }
7 showName(){
8 return this.name;
9 }
10 showAge(){
11 return this.age;
12 }
13 }
14
15 var p1 = new Person();
16 console.log(p1.name); // 构造器里面给的默认值 default
17 console.log(p1.age); // 构造器里面给的默认值 0
4. 传统写法原型继承extends
1 //传统写法原型继承
2 function Person(name,age){ // 类、构造函数
3 this.name = name;
4 this.age = age;
5 }
6 Person.prototype.showName = function(){
7 return this.name;
8 };
9 Person.prototype.showAge = function(){
10 return this.age;
11 };
12 // 工人类
13 function Worker(name,age){
14 // 属性继承过来
15 Person.apply(this,arguments);
16 }
17 // 原型继承
18 Worker.prototype = new Person();
19 var p1 = new Person('allen',28);
20 var w1 = new Person('worker',1000);
21 console.log(w1.showName()); // 确实继承过来了 result:worker
5. ES6中面向对象实现类继承
1 class Person{
2 // 构造器
3 constructor(name,age){
4 this.name = name;
5 this.age = age;
6 }
7 showName(){
8 return this.name;
9 }
10 showAge(){
11 return this.age;
12 }
13 }
14 class Worker extends Person{
15 constructor(name,age,job='啦啦啦'){
16 // 继承超父类的属性
17 super(name,age);
18 this.job = job;
19 }
20 showJob(){
21 return this.job;
22 }
23 }
24 var p1 = new Person('aaa',18);
25 var w1 = new Person('www',36);
26 var w2 = new Worker('wwwwwwww',90);
27 console.log(w1.showName()); // www
28 console.log(w2.showJob()); // 默认给的值 ‘啦啦啦’
10. 模块化 export 和 import
import 导入模块、export 导出模块
可以直接在任何变量或者函数前面加上一个 export
关键字,就可以将它导出。
在一个文件中:
1 export const sqrt = Math.sqrt;
2 export function square(x) {
3 return x * x;
4 }
5 export function diag(x, y) {
6 return sqrt(square(x) + square(y));
7 }
然后在另一个文件中这样引用:
1 import { square, diag } from 'lib';
2 console.log(square(11)); // 121
3 console.log(diag(4, 3));
总结:
1 //mod.js
2 // 第一种模块导出的书写方式(一个个的导出)
3 // 导出普通值
4 export let a = 12;
5 export let b = 5;
6 // 导出json
7 export let json = {
8 a,
9 b
10 };
11 // 导出函数
12 export let show = function(){
13 return 'welcome';
14 };
15 // 导出类
16 export class Person{
17 constructor(){
18 this.name = 'jam';
19 }
20 showName(){
21 return this.name;
22 }
23 }
24
25 //index.js
26 //导出模块如果用default了,引入的时候直接用,若没有用default,引入的时候可以用{}的形式
27 // 导入模块的方式
28 import {
29 a,
30 b,
31 json,
32 show,
33 Person
34 } from './mod.js';
35 console.log(a); // 12
36 console.log(b); // 5
37 console.log(json.a); // 12
38 console.log(json.b); // 5
39 console.log(show()); // welcome
40 console.log(new Person().showName()); // jam
41
42 //mod1.js
43 // 第二种模块导出的书写方式
44 let a = 12;
45 let b = 5;
46 let c = 10;
47 export {
48 a,
49 b,
50 c as cc // as是别名,使用的时候只能用别名,特别注意下
51 };
52
53 //index1.js
54 // 导入模块的方式
55 import {
56 a,
57 b,
58 cc // cc是导出的,as别名
59 } from './mod1.js';
60 console.log(a); // 12
61 console.log(b); // 5
62 console.log(cc); // 10
63
64 //mod2.js
65 // 第三种模块导出的书写方式 ---> default
66 // default方式的优点,import无需知道变量名,就可以直接使用,如下
67 // 每个模块只允许一个默认出口
68 var name = 'jam';
69 var age = '28';
70 export default {
71 name,
72 age,
73 default(){
74 console.log('welcome to es6 module of default...');
75 },
76 getName(){
77 return 'bb';
78 },
79 getAge(){
80 return 2;
81 }
82 };
83
84 //index2.js
85 // 导入模块的方式
86 import mainAttr from './mod2.js';
87 var str = ' ';
88 // 直接调用
89 console.log(`我的英文名是:${mainAttr.name}我的年龄是${mainAttr.age}`);
90 mainAttr.default(); // welcome to es6 module of default...
91 console.log(mainAttr.getName()); // bb
92 console.log(mainAttr.getAge()); // 2
93
94 //mod3.js
95 var name = 'jam';
96 var age = '28';
97 export function getName(){
98 return name;
99 };
100 export function getAge(){
101 return age;
102 };
103
104 //index3.js
105 // 导入模块的方式
106 import * as fn from './mod3.js';
107 // 直接调用
108 console.log(fn.getName()); // jam
11. Promise
在promise之前代码过多的回调或者嵌套,可读性差、耦合度高、扩展性低。通过Promise机制,扁平化的代码机构,大大提高了代码可读性;用同步编程的方式来编写异步代码,保存线性的代码逻辑,极大的降低了代码耦合性而提高了程序的可扩展性。
就是用同步的方式去写异步代码。
1 //Promise对象 ---> 用来传递异步操作过来的数据的
2 //Pending(等待、处理中) ---> Resolve(完成,fullFilled) ---> Reject(拒绝,失败)
3 //这里只是定义,还没开始执行
4 var p1 = new Promise(function(resolve,reject){
5 resolve(1); // 成功了,返回一个promise对象1
6 // reject(2); // 失败了
7 });
8
9 // 接收成功和失败的数据,通过then来传递
10 // then也是返回一个promise对象,会继续往下传递数据,传递给下一个then
11 p1.then(function(value){
12 // resolve
13 console.log(value); //执行打印1
14 return value + 1; // 1
15 alert(`成功了:${value}`);
16 },function(value){
17 // reject
18 alert(`失败了:${value}`);
19 }).then(function(value){
20 console.log(value); // 2
21 });
22
23 //catch捕获异常错误
24 var p1 = new Promise(function(resolve,reject){
25 resolve('成功了'); //返回一个promise对象“成功了”
26 });
27 //then也是返回一个promise对象,会继续往下传递数据
28 p1.then(function(value){
29 console.log(value); //打印“成功了”
30 // throw是用来抛错误的
31 throw '发生了点小意外';
32 }).catch(function(e){
33 // catch用来捕获这个错误的 ---> 追踪
34 console.log(e);
35 });
36
37 //all ---> 全部,用于将多个promise对象,组合,包装成
38 //Promise.all([p1,p2,p3,...]); 所有的promise对象,都正确,才走成功
39 //否则,只要有一个错误,就走失败
40 var p1 = Promise.resolve(1);
41 var p2 = Promise.reject(0);
42 Promise.all([true,p1,p2]).then(function(obj){
43 console.log(`成功了:${obj}`);
44 },function(obj){
45 console.log(`失败了:${obj}`);
46 });
47
48 // race ---> 返回的也是一个promise对象
49 //最先执行的的promise结果,哪个最快我用哪个,所以下面打印的是one
50 var p1 = new Promise(function(resolve,reject){
51 setTimeout(resolve,50,'one');
52 });
53 var p2 = new Promise(function(resolve,reject){
54 setTimeout(resolve,100,'two');
55 });
56 Promise.race([p1,p2]).then(function(val){
57 console.log(val);
58 });
59
60 //resolve ---> 生成一个成功的promise对象
61 //语法规则:Promise.resolve(val); // 普通值
62 // Promise.resolve(arr); // 数组之类
63 //Promise.resolve(promise); // 传递另一个promise对象
64 //传递普通值
65 Promise.resolve('success').then(function(val){
66 // 注意resolve,走得是这里
67 console.log(val); // success
68 },function(err){
69 console.log("err:"+ err);
70 });
71 //传递数组
72 Promise.resolve([1,2,3]).then(function(val){
73 // 注意resolve,走得是这里
74 console.log(val); // [1,2,3]
75 },function(err){
76 console.log(err);
77 });
78 //传递一个promise对象
79 var p1 = Promise.resolve(520);
80 var p2 = Promise.resolve(p1);
81 p2.then(function(val){
82 //从p1那边传递过来的
83 console.log(val); // 520
84 });
再来一道经典面试题:
1 setTimeout(function() {
2 console.log(1)
3 }, 0);
4 new Promise(function executor(resolve) {
5 console.log(2);
6 for( var i=0 ; i<10000 ; i++ ) {
7 i == 9999 && resolve();
8 }
9 console.log(3);
10 }).then(function() {
11 console.log(4);
12 });
13 console.log(5);
首先先碰到一个 setTimeout,于是会先设置一个定时,在定时结束后将传递这个函数放到任务队列里面,因此开始肯定不会输出 1 。
然后是一个 Promise,里面的函数是直接执行的,因此应该直接输出 2 3 。
然后,Promise 的 then 应当会放到当前 tick 的最后,但是还是在当前 tick 中。
因此,应当先输出 5,然后再输出 4 。
最后在到下一个 tick,就是 1 。
“2 3 5 4 1”
12. Generator、yield
生成器( generator)是能返回一个迭代器的函数。生成器函数也是一种函数,最直观的表现就是比普通的function多了个星号*,在其函数体内可以使用yield关键字,有意思的是函数会在每个yield后暂停。
这里生活中有一个比较形象的例子。咱们到银行办理业务时候都得向大厅的机器取一张排队号。你拿到你的排队号,机器并不会自动为你再出下一张票。也就是说取票机“暂停”住了,直到下一个人再次唤起才会继续吐票。
当你调用一个generator时,它将返回一个迭代器对象。这个迭代器对象拥有一个叫做next的方法来帮助你重启generator函数并得到下一个值。next方法不仅返回值,它返回的对象具有两个属性:done和value。value是你获得的值,done用来表明你的generator是否已经停止提供值。继续用刚刚取票的例子,每张排队号就是这里的value,打印票的纸是否用完就这是这里的done。
看个例子:
// 生成器
function *createIterator() {
yield 1;
yield 2;
yield 3;
} // 生成器能像正规函数那样被调用,但会返回一个迭代器
let iterator = createIterator(); console.log(iterator.next().value); // 1
console.log(iterator.next().value); // 2
console.log(iterator.next().value); // 3
console.log(iterator.next().value); // undefined 因为generator已经停止提供值
1 //Generator ---> 生成器就是一个函数
2 //特点:
3 //1.函数名前面带一个*,和普通函数做区分
4 //2.内部使用yield语句
5 //调用方式,如下var res = show(); 与普通函数一样
6 //value指的是generator函数内容yield定义的值,done:false表示还没遍历完
7 //直接找到返回值return了,那么此时done才会为true
8 //console.log(res.next());{value:'值1',done:false}
9 function* show(){
10 yield 'Hello';
11 yield 'World';
12 yield 'ES6';
13 return 'xx';
14 }
15 var res = show();
16 console.log(res.next()); // {value: "Hello", done: false}
17 console.log(res.next()); // {value: "World", done: false}
18 console.log(res.next()); // {value: "ES6", done: false}
19 console.log(res.next()); // {value: "allen", done: true}
20 // 已经找到return返回值了,继续下去就没有意义了
21 // console.log(res.next()); // {value: "undefined", done: true}
22
23 //yield本身没有返回值,或者可以说每次给你返回的是undefined
24 function* show(){
25 var a = yield 'Hello';
26 return a;
27 }
28 var res = show();
29 console.log(res.next()); // {value: "Hello", done: false}
30 console.log(res.next()); // {value: "undefined", done: true}
31
32 //next方法是可以带参数的,死循环的generator函数
33 function* fn(){
34 for(var i=0;true;i++){
35 // 如果里面传了一个值,那么它会把这个参数赋给最近的一个yield
36 var a = yield i;
37 if(a) i = -1;
38 }
39 }
40 var d = fn();
41 console.log(d.next()); // {value: 0, done: false}
42 console.log(d.next()); // {value: 1, done: false}
43 console.log(d.next()); // {value: 2, done: false}
44 // 如果里面传了一个值,那么它会把这个参数赋最近的一个yield
45 console.log(d.next(true)); // {value: 0, done: false}
46 console.log(d.next()); // {value: 1, done: false}
47 console.log(d.next()); // {value: 2, done: false}
48 console.log(d.next()); // {value: 3, done: false}
49
50 // for..0f循环generator函数
51 function* fn(){
52 yield 1;
53 yield 2;
54 yield 3;
55 yield 4;
56 yield 5;
57 return 6;
58 }
59 //for..0f循环generator函数,可以取值
60 for(let val of fn()){
61 document.write(val); // 12345
62 }
63
64 // 对象里使用generator函数的特殊写法,注意下
65 var json = {
66 *show(){
67 yield 'a';
68 yield 'b';
69 return 'c';
70 }
71 };
72 var res = json.show();
73 console.log(res.next()); // {value: "a", done: false}
74 console.log(res.next()); // {value: "b", done: false}
75 console.log(res.next()); // {value: "c", done: true}
自动调用生成器并启动迭代器的方法:
1 function run(taskDef) { //taskDef即一个生成器函数
2
3 // 创建迭代器,让它在别处可用
4 let task = taskDef();
5
6 // 启动任务
7 let result = task.next();
8
9 // 递归使用函数来保持对 next() 的调用
10 function step() {
11
12 // 如果还有更多要做的
13 if (!result.done) {
14 console.log(result.value); //这里就执行该做的事
15 result = task.next();
16 step();
17 }
18 }
19
20 // 开始处理过程
21 step();
22
23 }
24 //生成器
25 function *createIterator() {
26 yield 1;
27 yield 2;
28 yield 3;
29 }
30 //启动
31 run(createIterator);
原文:https://www.cnblogs.com/ainyi/p/8537027.html
ES6常用的更多相关文章
- ES6常用语法
ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准.因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015. 也就是说,ES6就是ES2015. ...
- ES6常用新特性
https://segmentfault.com/a/1190000011976770?share_user=1030000010776722 该文章为转载文章!仅个人喜好收藏文章! 1.前言 前几天 ...
- ES6常用特性总览
以前看过一遍es6,今天面试时被问到了一个很简单的es6特性,竟然没回答上来,特来重温一下es6,做个总结性笔记. 一.什么是es6 es6是新版本JavaScript语言的标准,在2015年6月发布 ...
- ES6常用对象操作
ES6常用对象操作 一. const 简单类型数据常量 // const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动.对于简单类型的数据(数值.字符串.布尔值),值就保存在 ...
- ES6常用语法总结
ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准.因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015.也就是说,ES6就是ES2015.虽 ...
- es6常用基础合集
es6常用基础合集 在实际开发中,ES6已经非常普及了.掌握ES6的知识变成了一种必须.尽管我们在使用时仍然需要经过babel编译. ES6彻底改变了前端的编码风格,可以说对于前端的影响非常巨大.值得 ...
- ES6常用语法简介import export
ES6常用语法简介import export let与var用法区别 //var var a = []; for (var i = 0; i < 10; i++) { a[i] = functi ...
- es6常用功能与异步详解(JS高级面试题)
callback hell方法的使用 可读性不友好 function loadImg(src,callback,fail){ var img = document.createElement('img ...
- ES5与ES6常用语法教程之 ②解构语法糖、声明变量异同
js常用语法系列教程如下 es5与es6常用语法教程(1) es5与es6常用语法教程(2) es5与es6常用语法教程(3) es5与es6常用语法教程(4) es5与es6常用语法教程(5) es ...
- vue学习(一)ES6常用语法
1 ES6常用语法 1.1 变量提升 例① # 变量提升 <div id="app"> </div> <script> console.log( ...
随机推荐
- [Swift]LeetCode541. 反转字符串 II | Reverse String II
Given a string and an integer k, you need to reverse the first k characters for every 2k characters ...
- redis缓存使用
什么是缓存(cache): 在项目中没有必要每次请求都查询数据库的情况就可以使用缓存,让每次请求先查询缓存,如果命中,就直接返回缓存结果,如果没有命中,就查询数据库, 并将查询结果放入缓存,下次请求时 ...
- NumPy 学习笔记(三)
NumPy 数组操作: 1.修改数组形状 a.numpy.reshape(arr, newshape, order='C') 在不改变数据的条件下修改形状 b.numpy.ndarray.flat 是 ...
- Spring设计模式_策略模式/其他
策略模式特性 1.执行最终结果一样 2.执行过程和执行逻辑不一样 3.使用同一接口 达到目的就可以了 Git地址 https://github.com/wujiachengSH/WjcStrategy ...
- HBase篇--HBase常用优化
一.前述 HBase优化能够让我们对调优有一定的理解,当然企业并不是所有的优化全都用,优化还要根据业务具体实施. 二.具体优化 1.表的设计 1.1 预分区 默认情况下,在创建HBase表的时候会自 ...
- 『离散化 discrete』
离散化(discrete) 离散化可以说是一个很基础的算法吧,但是有些时候还是很好用很有必要的算法. 离散化的排序的一个运用,具体地讲,离散化算法是将无穷大集合中的若干个元素映射到有限大小的集合中,以 ...
- AngularJS7那些不得不说的事故
题外话 最近简直要忙死,所以停更了很久,你们会不会以为我人间蒸发了? 正文之前,请允许我先跑个题,就是关于忙的问题. 做了Freelance,每天过的比上班还累,这完全不是我想要的生活啊? ...
- java基础4:深入理解final关键字
本文主要介绍了final关键字的使用方法及原理 具体代码在我的GitHub中可以找到 https://github.com/h2pl/MyTech 文章首发于我的个人博客: https://h2pl. ...
- 设计模式总结篇系列:单例模式(SingleTon)
在Java设计模式中,单例模式相对来说算是比较简单的一种构建模式.适用的场景在于:对于定义的一个类,在整个应用程序执行期间只有唯一的一个实例对象.如Android中常见的Application对象. ...
- docker 安装LAMP环境
LAMP:Linux.Apache.MySQL.PHP docker hub 上会有配好的LAMP环境docker,部署到本地并运行起来 sudo docker pull linode/lamp 然后 ...