(一)Iterator遍历器
遍历器是一种接口,它为不同的数据结构提供了统一的访问机制。
如果一个数据结构具有遍历器接口,那么就可以依次处理该数据结构的成员。
当前javascript用来表示集合的数据结构有四种,分别是数组、对象、Set和Map,并且这四种数据结构可以相互嵌套使用,比如数组的成员可以是对象,对象的成员又可以是Set等等。
一.遍历器接口:
如果一个结构具有Symbol.iterator属性,那么就称这个数据结构具有遍历器接口。
Symbol.iterator返回Symbol对象的iterator属性,这是一个预定义好的、类型为Symbol的特殊值。
Symbol.iterator属性指向一个方法,调用此方法返回一个遍历器对象,它是一个指针对象,默认指向数据结构的起始位置。
let arr = ["源库网", 4, "www.yuankuwang.com", "北京大学"]; let it = arr[Symbol.iterator](); console.log(it.next()); console.log(it.next()); console.log(it.next()); //搞笑遍历 let arr = ["源库网", 4, "北京大学"]; let it = arr[Symbol.iterator](); //循环器(效率高) for(;;) { let nextEle = it.next(); if(nextEle.done) { break } console.log(nextEle.value); } //每一次调用next()方法都会返回一个对象,此对象包含value和done属性,value属性值是数据结构成员的值,如果遍历完成value属性值为undefined;done属性是一个布尔值,如果为true,说明遍历完成,如果为false,说明遍历尚未完成 复制代码
二.默认具有遍历器接口的数据结构,for of循环
当对一个数据结构使用for of循环遍历的时候,会自动调用遍历器接口。
ES6中有四类数据结构默认具有遍历器接口:
(1)数组
(2)某些类数组
(3)Map
(4)Set
var arr = [1,2,3,'aa','bb','cc']; for(let elem of arr) { console.log(elem); } 某些类数组: let obj = { data: ["aa","bb",'cc',3,9,8], [Symbol.iterator]() { const self = this; let index = 0; return { next() { if (index < self.data.length) { return { value: self.data[index++], done: false }; } else { return { value: undefined, done: true }; } } }; } }; let it = obj[Symbol.iterator](); console.log(it.next().value) 复制代码
三、展开运算符:
如果一个数据结构具有遍历器接口,那么除了可以使用for of循环以外,也可以使用展开运算符。
代码实例如下:
let arr = ["源库网", 4, "www.yuankuwang.com"]; console.log(...arr); 复制代码
(二)Generator
Generator函数是ES6新增的一种异步编程方案。
说明:Generator函数指的是一种新的语法结构,是一个遍历器对象生成器,它内部可以封装多个状态,非常适合用于异步操作。
【语法】
Generator函数语法和普通的function函数类似,但是有三个不同点:
(1)function关键字和函数名称之间有一个星号(*)。
(2)函数体内可以使用yield语句。
(3)函数调用后不会立即执行,返回的是一个遍历器对象。
//一个Generator函数 function* yuanku() { yield "源库网"; yield "北京海淀"; yield "www.yuankuwang.com"; return "end"; } //函数内部使用yield语句定义不同的状态,return也可以定义一个状态,也就是说上面代码有四个状态 var y = yuanku(); //调用此函数,并不会立即执行它其中的代码,而是返回一个遍历器对象 console.log(y.next()); //返回一个具有value和done属性的对象 console.log(y.next()); //有return,返回{value:end,done:true};如果没有return,返回{value: undefined, done: true} 复制代码
yield语句:
每一个yield语句定义不同的状态,它也是一个代码执行暂停标识。
yield语句不能在普通函数中使用,否则会报错。
调用Generator函数可以返回一个遍历器对象,要想访问Generator函数中的每一个状态,需要使用遍历器对象调用next()方法。
如果yield语句作为其他语句的一部分,那么必须使用小括号包裹,否则会报错
function *yuanku() { //console.log("欢迎来到" + yield "源库网");//报错 console.log("欢迎来到" + (yield "源库网"));//正确 } let y = yuanku(); console.log(y.next().value); //先返回yield console.log(y.next().value); //再返回return,yield为undefined 复制代码
next()方法:
next()一个主要功能,就是从暂停状态继续下一段代码的执行。
next()还有一个重要的功能,那就是可以接受一个参数,此参数作为上一个yield语句的返回值。
虽然当代码执行到yield语句的时候,能够将其后面的表达式的值作为对象的value属性值,但是默认情况下yield语句是没有返回值的,或者说它的返回值是undefined
注意:yield语句的返回值和yield后面表达式的返回值是两个概念
向next中传值,!!!此值作为上一个yield的返回值!!!
function* yuanku(num) { let x = 2 * (yield num); console.log('x='+x); let y = yield x*3; console.log('y='+y); console.log(x,y); } var g=yuanku(5); console.log(g.next());//{value:5,done:false},第1个next传值无意义,因为没有上一个yield console.log(g.next());//x=NaN {value:NaN,done:false} console.log(g.next(3));//{value:12,done:false} console.log(g.next(3));//{value:undefined,done:true} //-----------异步方法实测------------------------- setTimeout(function () { console.log("hello"); },3000); let y; var func = function(time) { setTimeout(function() { console.log(time, " on"); y.next(true); }, time); }; var gen = function * () { var f1 = yield func(3000); console.log('f1:', f1); var f2 = yield func(1000); console.log('f2:', f2); }; y = gen(); y.next(); console.log('end'); 复制代码
作者:zhulin1028
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。