从 “不会迭代” 到 “面试加分”:JS 迭代器现场教学

大家好,今天我们来聊聊 JavaScript 迭代器。别急着关掉页面,保证你看完不仅能学会迭代器,还能收获意料之外的知识

前言

你是否曾经在 for-of 循环前一脸懵逼?是否在面试官问你"迭代器协议"时只会尴尬微笑?今天这篇文章,带你从原理到实战,从协议到骚操作,彻底掌握迭代器!


1. 什么是迭代器?

迭代器就是一个能帮你"一个一个"拿数据的小工具。比如你有一堆糖果,迭代器就像一个自动分糖机,每次给你一个,直到分完。

在 JavaScript 里,迭代器是实现了 next() 方法的对象,每次调用 next(),它会返回一个形如 { value, done } 的对象。

2. for-of 的底层原理

for-of 能遍历数组、字符串、Map、Set......但它的本质其实是:

  1. 先获取对象的 Symbol.iterator 属性
  2. 调用它得到一个迭代器对象
  3. 不断调用迭代器的 next() 方法,直到 done: true
javascript 复制代码
const arr = [1, 2, 3, 4, 5]
simpleForOf(arr, (item) => {
    console.log(item);
}) // 1, 2, 3, 4, 5

function simpleForOf(iterable, callback) {
    const iterator = iterable[Symbol.iterator]()
    while (true) {
        const {value, done}
        // console.log(value);
        callback(value) = iterator.next() // {value: 1, done: false}
        if (done) {
            break
        }
    }
}

代码解析

  • simpleForOf 就是 for-of 的底层实现!
  • 通过 Symbol.iterator 拿到迭代器,然后不断 next()
  • 每次拿到一个值,执行回调。

这就是 for-of 的灵魂!

3. 迭代器协议和 Symbol.iterator

markdown 复制代码
# for of
 - 只能遍历拥有迭代器属性的对象  

 - 原理

# 迭代器属性
[Symbol.iterator]: function() {}

# 迭代器协议

重点

  • 只有实现了 [Symbol.iterator] 方法的对象才能被 for-of 遍历。
  • 迭代器协议要求对象有一个 next() 方法,每次返回 { value, done }

4. 手写迭代器,骚操作一箩筐

手写一个迭代器:

javascript 复制代码
function createIterator(arr) {
    let index = 0
    return {
        next: function() {
            if (index < arr.length) {
                return {value: arr[index++], done: false}
            }
            return {value: undefined, done: true}
        }
    }
}
const myIterator = createIterator([1, 2, 3])
console.log(myIterator.next()); // { value: 1, done: false }
console.log(myIterator.next()); // { value: 2, done: false }
console.log(myIterator.next()); // { value: 3, done: false }
console.log(myIterator.next()); // { value: undefined, done: true }

代码解析

  • createIterator 返回一个有 next() 方法的对象。
  • 每次调用 next(),返回当前值和是否结束。
  • 这就是迭代器协议的标准实现!

手写迭代器,面试官看了都要点赞!👍

5. 对象也能 for-of?

正常情况下,对象不能 for-of,因为没有实现 [Symbol.iterator]。但你在自己给它加一个迭代器, 看我如何玩出花:

方案一:原型上加迭代器

javascript 复制代码
Object.prototype[Symbol.iterator] = function*() {
    return yield* Object.values(this)
}

let [a, b] = {a: 1, b: 2}
console.log(a, b)

代码解析

  • 给所有对象加上 [Symbol.iterator],让它们可以 for-of!
  • 用生成器 function*,直接 yield 出所有值。
  • 这样就能解构对象了!

方案二:对象自定义迭代器

javascript 复制代码
let obj = {
    a: 1,
    b: 2,
    c: 3
}
obj[Symbol.iterator] = function() {
    let index = 0
    let keys = Object.keys(this)
    return {
        next: () => {
            if (index < keys.length) {
                return {value: this[keys[index++]], done: false}
            }
            return {value: undefined, done: true}
        }
    }
}

代码解析

  • 给单个对象加迭代器属性。
  • 遍历对象的 key,每次返回对应的 value。

这样对象也能 for-of,骚操作 get!😎

方案三: 借用数组的迭代器

js 复制代码
Object.prototype[Symbol.iterator] = function() {
    return Object.values(this)[Symbol.iterator]() 
}

代码解析

  • 直接用Object.values方法获取到对象上的所有属性值返回一个数组
  • 让对象的迭代器等于对象值数组的迭代器

让数组的迭代器顶替对象的迭代器,一手狸猫换太子😎

6. for-in 和 for-of 的区别

javascript 复制代码
let arr = [1, 2, 3]
for (let index in arr) {
    console.log(index, arr[index])
}

代码解析

  • for-in 遍历的是索引(key),而不是值。
  • for-of 遍历的是值。

对象的 for-in

javascript 复制代码
let obj = {
    a: 1,
    b: 2,
    c: 3
}
for (let key in obj) { // 可以遍历到对象原型上的属性
    console.log(key, obj[key])
}

for-in 会遍历原型上的属性,for-of 只遍历迭代器返回的值。

7. 总结与面试技巧

面试官问你 for-of 原理?

  • 说出 Symbol.iterator,迭代器协议,next 方法,done 属性。
  • 能手写一个迭代器,面试官直接给你 Offer!

for-in 和 for-of 的区别?

  • for-in 遍历 key,for-of 遍历 value。
  • for-in 能遍历原型链,for-of 只遍历迭代器返回的内容。

对象能不能 for-of?

  • 默认不能,但可以自己加 Symbol.iterator。
  • 还能用生成器让对象支持解构。

结语

迭代器其实很简单,只要你敢动手写一遍,面试、项目都能用得上!

最后送你一句话:

"会写迭代器的人,代码都不会太差!"


祝你面试顺利,代码越写越骚!

相关推荐
GalaxyMeteor2 小时前
Elpis 开发框架搭建第二期 - Webpack5 实现工程化建设
前端
我的写法有点潮2 小时前
最全Scss语法,赶紧收藏起来吧
前端·css
小高0073 小时前
🧙‍♂️ 老司机私藏清单:从“记事本”到“旗舰 IDE”,我只装了这 12 个插件
前端·javascript·vue.js
Mo_jon3 小时前
css 遮盖滚动条,鼠标移上显示
前端·css
EveryPossible3 小时前
终止异步操作
前端·javascript·vue.js
Stringzhua3 小时前
setup函数相关【3】
前端·javascript·vue.js
neon12043 小时前
解决Vue Canvas组件在高DPR屏幕上的绘制偏移和区域缩放问题
前端·javascript·vue.js·canva可画
Sammyyyyy4 小时前
Node.js 做 Web 后端优势为什么这么大?
开发语言·前端·javascript·后端·node.js·servbay
妮妮喔妮4 小时前
Webpack 有哪些特性?构建速度?如何优化?
前端·webpack·node.js