Iterator迭代器

简要描述:

  • 一种接口机制,为各种不同的数据结构提供统一访问的机制。
  • 主要供for...of消费。
  • 一句话 :不支持遍历的数据结构“可遍历”。
    原生具备 Iterator 接口的数据结如下,可通过for...of进行遍历:
    Array、Map、Set、String、TypedArray(用于二进制数据的)、函数的arguments对象、NodeList对象
1. 模拟一个iterator执行
function makeIterator(arr) {
    let nextIndex = 0;
    return {
        next() {
            return nextIndex < arr.length ? 
              { value: arr[nextIndex++], done: false  } : { value: undefined, done: true }
        }
    }
}
let it = makeIterator(['a', 'b', 'c'])
console.log(it.next()); //{value: 'a', done: false}
console.log(it.next()); //{value: 'b', done: false}
console.log(it.next()); //{value: 'c', done: false}
console.log(it.next()); //{value: undefined, done: true}

以上是不是让你想起了Generator函数,调用方式也是通过next一次一次调,打印的数据结构也一样,Generator函数内部封装了迭代器。

2. 拿数组举例
let arr = [1, 2, 3]
for (let key of arr) {
    console.log(key)
}
console.log(Symbol.iterator) //Symbol(Symbol.iterator)
let ite = arr[Symbol.iterator](); 
console.log(ite) //Array Iterator {}
console.log(ite.next()) //{value: 1, done: false}
console.log(ite.next()) //{value: 2, done: false}
console.log(ite.next()) //{value: 3, done: false}
console.log(ite.next()) //{value: undefined, done: true}

控制台中打印arr,展开[[prototype]],发现有个Symbol(Symbol.iterator)属性,这个就是它的迭代器,就是数组能用for...of遍历的原因


image.png

想要数据能够用for...of进行遍历,就要给数据提供Iterator迭代器。

3. 为数据自定义迭代器

迭代器的条件

  • 可迭代协议:当前对象是否有 Symbol.iterator 属性
  • 迭代器协议:当前迭代器必须符合条件
return {
   next() {
       return { value: ... , done: ... }
   }
}

接下来,让我们为下面的courses自制迭代器 ,让courses能够用for...of遍历到每一个数组内的元素

let courses = {
    allCources: {
        frontend: ['ES', '小程序', 'Vue', 'React'],
        backend: ['Java', 'Python'],
        webapp: ['Android', 'IOS']
    }
}
courses[Symbol.iterator] = function () { //定义Symbol(Symbol.iterator)属性,值为iterator函数
    let allCources = this.allCources;
    let keys = Reflect.ownKeys(allCources) //取到数组的属性名,包括Symbol
    let values = [];//所有元素放到这里
    return {
        next() {
            if (!values.length) {
                if (keys.length) { //没有
                    // 往values里添加数据,确保每次的next调用,都能return出values中的值
                    values = allCources[keys[0]]; //keys每次从0开始取,取过的就shift删掉,避免取重复的
                    keys.shift();
                }
            }
            return {
                done: !values.length, //values要是空了,代表都取过了,返回true
                value: values.shift() //return出values中的值
            }
        }
    }
}
for (let key of courses) {
    console.log(key)
}
// 打印结果:ES 小程序 Vue React Java Python Android IOS
4. 异步迭代器
  • Symbol.asyncIterator
  • for await (...of...)
function getPromise(time) { //异步函数
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve({ value: time, done: false }) //next返回值
        }, time)
    })
}
let arr = [getPromise(1000), getPromise(2000), getPromise(3000)];//要被遍历的数组,数组元素都是异步函数

arr[Symbol.asyncIterator] = function () { //异步迭代器
    let nextIndex = 0;
    return {
        next() { //返回值为 在同步的返回值写法上包裹一层promise
            return nextIndex < arr.length ? arr[nextIndex++] : Promise.resolve({ value: undefined, done: true })
        }
    }
}
async function test(){
    //for await(... of ...)等到当前元素完成再遍历下一个元素,并且遍历到的是异步完成的结果值
    for await (let item of arr){ //遍历到异步的结果
        console.log(item) //1000 2000 3000
    }
}
test(); //调用异步函数
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355

推荐阅读更多精彩内容