1. 迭代器
迭代器是一种接口,为各种不同的数据结构提供统一的访问机制,任何数据结构,只要部署了iterator接口,就可以实现遍历操作
(1)ES6创造了一种新的遍历语法,for...of,iterator主要供 for...of 消费。
(2)原生具备iterator接口的数据结构,Arguments、Array、List、Set、Map、String、TypedArray、NodeList
const arr = ['tom','jerry','shuke','beita']
for(let item of arr){
console.log(item) // tom, jerry, shuke, beita
}
for(let key in arr){
console.log(key) // 0,1,2,3
}
(3)自定义迭代器
const obj = {
name:'obj',
attriArray:['one','two','three','four'],
// 想要一个对象能够拥有iterator迭代器,就必须让其具有Symbol.iterator属性
[Symbol.iterator](){
let index = 0
let _this = this
return {
next:function{
if(index < _this.attriArray.length){
const result = {
value:_this.attriArray[index],
done:false
}
index++
return result
}else{
const result = {
value:undefined,
done:true
}
return result
}
}
}
}
}
// 需求是,创建一个迭代器,当在迭代obj对象的时候,每次迭代输出结果是obj对象中attriArray数组的内容
for(let item of obj){
console.log(item) // one,two,three,four
}
2. 生成器函数
生成器函数就是一个特殊的函数,用来做异步编程的新的解决方案。使用 * 进行标识,配合yield关键字进行使用
1. 示例
// 在function关键字和函数名中间使用 * ,表示这个函数是一个生成器
// yield 可以看做是函数代码的分隔符,把函数体分成不同的代码块,
// 通过调用iterator.next()方法,来执行每一块的代码内容
function * gen(){
console.log('111')
yield 'hello'
console.log('222')
yield 'world'
console.log('333')
yield '!!!'
console.log('444')
}
let iterator = gen() // 生成器函数,返回一个迭代器对象
console.log(iterator) // 直接打印 gen {suspended}
iterator.next() // 111
iterator.next() // 222
iterator.next() // 333
iterator.next() // 444
// 打印iterator.next(),输出内容中的value就是yield后面表达式的执行结果
console.log(iterator.next())// {value:'hello', done:false}
console.log(iterator.next())// {value:'world', done:false}
console.log(iterator.next())// {value:'!!!', done:false}
console.log(iterator.next())// {value:undefined, done:true}
// 既然返回的是一个迭代器对象,就可以使用for...of进行遍历
for(let item of iterator){
console.log(itme)
}
// 打印结果
// 111
// hello
// 222
// world
// 333
// !!!
2. 生成器函数实例
实例1:1s 后输出111,再2s后输出222,再3s后输出333...
// 如果用普通回调来实现,会出现回调地狱现象
// setTimeout(() => {
// console.log(111);
// setTimeout(() => {
// console.log(222);
// setTimeout(() => {
// console.log(333)
// // 回调地狱...
// }, 3000);
// }, 2000);
// }, 1000);
// 使用生成器来实现需求
function one() {
setTimeout(() => {
console.log(111);
iterator.next();
}, 1000);
}
function two() {
setTimeout(() => {
console.log(222);
iterator.next();
}, 2000);
}
function three() {
setTimeout(() => {
console.log(333);
iterator.next();
}, 3000);
}
function * gen(){
yield one();
yield two();
yield three();
}
// 调用生成器函数
let iterator = gen();
iterator.next();
实例2:依次异步获取用户数据、订单数据、商品数据
// 异步编程
// 需求: 模拟获取数据流程 用户数据 > 订单数据 > 商品数据
function getUsers() {
setTimeout(() => {
let userData = '用户数据'
// 调用 next 方法,将用户数据传入,这里 next方法传入的参数,将作为函数体中第一个yield代码块的返回值
iterator.next(userData);
}, 1000);
}
function getOrders() {
setTimeout(() => {
let orderData = '订单数据'
// 调用 next 方法,将订单数据传入,这里 next方法传入的参数,将作为函数体中第二个yield代码块的返回值
iterator.next(orderData);
}, 1000);
}
function getGoods() {
setTimeout(() => {
let goodData = '商品数据'
// 调用 next 方法,将商品数据传入,这里 next方法传入的参数,将作为函数体中第三个yield代码块的返回值
iterator.next(goodData);
}, 1000);
}
// 声明生成器函数
function * gen(){
let users = yield getUsers();
console.log(users);
let orders = yield getOrders();
console.log(orders);
let goods = yield getGoods();
console.log(goods);
}
// 调用生成器函数
let iterator = gen();
iterator.next();