编程进阶网 编程进阶网
首页
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++开发技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • Android智能硬件
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Linux实践开发
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接

杨充

专注编程 · 终身学习者
首页
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++开发技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • Android智能硬件
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Linux实践开发
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接
  • README
  • C语言入门精通

  • Cpp入门到精通

  • Java入门精通

  • Go入门到精通

  • JavaScript入门

    • 基础入门

      • README
      • 入门介绍
      • 数据类型
      • 运算符
      • 函数
      • 面向对象
      • 标准库
      • 异步操作
      • 事件设计
      • 错误机制
      • 模块开发
      • 字符串处理
      • 迭代器与生成器
        • 12.1 迭代协议
          • 12.1.1 可迭代协议(Iterable Protocol)
          • 12.1.2 迭代器协议(Iterator Protocol)
          • 12.1.3 自定义可迭代对象
          • 12.1.4 迭代器的消费者
          • 12.1.5 提前终止:return() 和 throw()
        • 12.2 生成器函数
          • 12.2.1 基本语法
          • 12.2.2 yield 的双向通信
          • 12.2.3 return() 和 throw()
          • 12.2.4 yield* 委托
        • 12.3 生成器的实用模式
          • 12.3.1 无限序列
          • 12.3.2 惰性管道
          • 12.3.3 状态机
          • 12.3.4 协程(Coroutine)
          • 12.3.5 生成器实现 async/await
        • 12.4 异步迭代器
          • 12.4.1 异步迭代协议
          • 12.4.2 异步生成器
          • 12.4.3 流式数据处理
          • 12.4.4 并发控制
        • 12.5 内置可迭代对象详解
          • 12.5.1 Array 迭代器
          • 12.5.2 Map 和 Set 迭代器
          • 12.5.3 String 迭代器
          • 12.5.4 arguments 和 NodeList
        • 12.6 迭代器工具库
        • 12.7 生成器与迭代器对比
      • Symbol
      • DOM操作
      • 网络请求
    • 综合案例

    • 专栏博客

  • CodeX
  • JavaScript入门
  • 基础入门
杨充
2026-04-13
目录

迭代器与生成器

# 12.迭代器与生成器

迭代器(Iterator)和生成器(Generator)是 ES6 引入的核心特性,它们为 JavaScript 提供了统一的遍历接口和惰性求值能力。for...of、展开运算符、解构赋值等语法糖的底层都依赖迭代器协议。

# 12.1 迭代协议

# 12.1.1 可迭代协议(Iterable Protocol)

一个对象要成为"可迭代的",必须实现 [Symbol.iterator]() 方法,该方法返回一个迭代器对象。

// 内置可迭代对象
// Array、String、Map、Set、TypedArray、arguments、NodeList

const arr = [1, 2, 3];
const iterator = arr[Symbol.iterator]();

console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
1
2
3
4
5
6
7
8
9
10

# 12.1.2 迭代器协议(Iterator Protocol)

迭代器必须实现 next() 方法,返回 { value, done } 格式的对象:

// 手动实现一个迭代器
function createRangeIterator(start, end) {
    let current = start;
    return {
        next() {
            if (current <= end) {
                return { value: current++, done: false };
            }
            return { value: undefined, done: true };
        }
    };
}

const iter = createRangeIterator(1, 3);
iter.next(); // { value: 1, done: false }
iter.next(); // { value: 2, done: false }
iter.next(); // { value: 3, done: false }
iter.next(); // { value: undefined, done: true }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 12.1.3 自定义可迭代对象

class Range {
    constructor(start, end) {
        this.start = start;
        this.end = end;
    }
    
    [Symbol.iterator]() {
        let current = this.start;
        const end = this.end;
        
        return {
            next() {
                if (current <= end) {
                    return { value: current++, done: false };
                }
                return { value: undefined, done: true };
            },
            // 可选:让迭代器本身也可迭代
            [Symbol.iterator]() {
                return this;
            }
        };
    }
}

const range = new Range(1, 5);

// for...of
for (const n of range) {
    console.log(n); // 1, 2, 3, 4, 5
}

// 展开运算符
console.log([...range]); // [1, 2, 3, 4, 5]

// 解构赋值
const [a, b, c] = range; // a=1, b=2, c=3

// Array.from
Array.from(range); // [1, 2, 3, 4, 5]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

# 12.1.4 迭代器的消费者

以下语法结构会自动调用迭代器协议:

消费者 说明
for...of 循环遍历
...spread 展开运算符
[a, b] = iterable 解构赋值
Array.from() 转换为数组
new Map() / new Set() 构造集合
Promise.all() / Promise.race() 接受可迭代对象
yield* 委托生成器

# 12.1.5 提前终止:return() 和 throw()

迭代器可以选择实现 return() 和 throw() 方法,用于资源清理:

class FileLines {
    constructor(filename) {
        this.filename = filename;
    }
    
    [Symbol.iterator]() {
        let lineNo = 0;
        const lines = ['line1', 'line2', 'line3']; // 模拟文件行
        
        return {
            next() {
                if (lineNo < lines.length) {
                    return { value: lines[lineNo++], done: false };
                }
                return { value: undefined, done: true };
            },
            // for...of 中 break 时调用
            return() {
                console.log('Iterator closed, releasing resources');
                return { value: undefined, done: true };
            }
        };
    }
}

const file = new FileLines('test.txt');
for (const line of file) {
    console.log(line);
    if (line === 'line1') break; // 触发 return()
}
// 输出: line1, Iterator closed, releasing resources
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 12.2 生成器函数

# 12.2.1 基本语法

生成器函数使用 function* 声明,内部使用 yield 关键字暂停执行:

function* simpleGenerator() {
    console.log('开始执行');
    yield 1;
    console.log('继续执行');
    yield 2;
    console.log('最后一段');
    yield 3;
    console.log('执行结束');
}

const gen = simpleGenerator();
// 此时函数体未执行

gen.next(); // '开始执行'  → { value: 1, done: false }
gen.next(); // '继续执行'  → { value: 2, done: false }
gen.next(); // '最后一段'  → { value: 3, done: false }
gen.next(); // '执行结束'  → { value: undefined, done: true }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

关键概念:

  1. 调用生成器函数不执行函数体,返回一个生成器对象
  2. 每次调用 next() 执行到下一个 yield 暂停
  3. yield 表达式的值就是 next() 返回对象中的 value
  4. 函数执行完毕后 done 变为 true

# 12.2.2 yield 的双向通信

yield 不仅能输出值,还能接收值。next(value) 中传入的参数会成为上一个 yield 表达式的返回值:

function* dialog() {
    const name = yield '你叫什么名字?';
    const age = yield `${name},你多大了?`;
    return `${name} 今年 ${age} 岁`;
}

const gen = dialog();
console.log(gen.next());          // { value: '你叫什么名字?', done: false }
console.log(gen.next('Alice'));   // { value: 'Alice,你多大了?', done: false }
console.log(gen.next(25));        // { value: 'Alice 今年 25 岁', done: true }
1
2
3
4
5
6
7
8
9
10

执行流程解析:

第1次 next():        执行到第一个 yield,输出 '你叫什么名字?'
第2次 next('Alice'): 'Alice' 赋值给 name,执行到第二个 yield
第3次 next(25):      25 赋值给 age,执行 return
1
2
3

注意:第一次 next() 的参数会被忽略,因为此时没有待接收值的 yield。

# 12.2.3 return() 和 throw()

function* gen() {
    try {
        yield 1;
        yield 2;
        yield 3;
    } catch (e) {
        console.log('捕获错误:', e.message);
    } finally {
        console.log('清理资源');
    }
}

// return() - 提前终止生成器
const g1 = gen();
g1.next();            // { value: 1, done: false }
g1.return('结束');     // '清理资源'  { value: '结束', done: true }
g1.next();            // { value: undefined, done: true }

// throw() - 向生成器内部抛出错误
const g2 = gen();
g2.next();            // { value: 1, done: false }
g2.throw(new Error('出错了'));
// '捕获错误: 出错了'
// '清理资源'
// { value: undefined, done: true }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 12.2.4 yield* 委托

yield* 将迭代控制权委托给另一个可迭代对象或生成器:

function* inner() {
    yield 'a';
    yield 'b';
    return 'inner done'; // return 值是 yield* 的结果
}

function* outer() {
    yield 1;
    const result = yield* inner(); // 委托给 inner
    console.log('inner 返回:', result);
    yield 2;
}

console.log([...outer()]); 
// inner 返回: inner done
// [1, 'a', 'b', 2]
// 注意:inner 的 return 值不在遍历结果中

// yield* 可以委托给任何可迭代对象
function* chars(str) {
    yield* str; // 字符串是可迭代的
}
console.log([...chars('hello')]); // ['h', 'e', 'l', 'l', 'o']
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

yield 实现树的深度优先遍历*:

class TreeNode {
    constructor(value, children = []) {
        this.value = value;
        this.children = children;
    }
    
    *[Symbol.iterator]() {
        yield this.value;
        for (const child of this.children) {
            yield* child; // 递归委托
        }
    }
}

const tree = new TreeNode('root', [
    new TreeNode('A', [
        new TreeNode('A1'),
        new TreeNode('A2'),
    ]),
    new TreeNode('B', [
        new TreeNode('B1'),
    ]),
]);

console.log([...tree]); // ['root', 'A', 'A1', 'A2', 'B', 'B1']
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 12.3 生成器的实用模式

# 12.3.1 无限序列

生成器可以表示无限序列,只在需要时计算值(惰性求值):

// 自然数
function* naturals(start = 1) {
    let n = start;
    while (true) {
        yield n++;
    }
}

// 斐波那契数列
function* fibonacci() {
    let [a, b] = [0, 1];
    while (true) {
        yield a;
        [a, b] = [b, a + b];
    }
}

// 取前 10 个斐波那契数
function take(n, iterable) {
    const result = [];
    for (const value of iterable) {
        result.push(value);
        if (result.length >= n) break;
    }
    return result;
}

console.log(take(10, fibonacci()));
// [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 12.3.2 惰性管道

将多个转换操作组合成惰性求值管道,避免创建中间数组:

function* map(iterable, fn) {
    for (const value of iterable) {
        yield fn(value);
    }
}

function* filter(iterable, pred) {
    for (const value of iterable) {
        if (pred(value)) yield value;
    }
}

function* takeWhile(iterable, pred) {
    for (const value of iterable) {
        if (!pred(value)) return;
        yield value;
    }
}

// 找出 1000 以内所有斐波那契偶数
const result = [
    ...filter(
        takeWhile(fibonacci(), n => n < 1000),
        n => n % 2 === 0
    )
];
console.log(result); // [0, 2, 8, 34, 144, 610]
// 没有创建任何中间数组!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 12.3.3 状态机

生成器天然适合表达状态机,每个 yield 是一个状态:

function* trafficLight() {
    while (true) {
        yield '🔴 红灯 - 停止';
        yield '🟢 绿灯 - 通行';
        yield '🟡 黄灯 - 减速';
    }
}

const light = trafficLight();
light.next().value; // '🔴 红灯 - 停止'
light.next().value; // '🟢 绿灯 - 通行'
light.next().value; // '🟡 黄灯 - 减速'
light.next().value; // '🔴 红灯 - 停止'(循环)
1
2
3
4
5
6
7
8
9
10
11
12
13

# 12.3.4 协程(Coroutine)

生成器可以实现协程模式,多个执行流交替执行:

function* taskA() {
    console.log('A: 步骤 1');
    yield;
    console.log('A: 步骤 2');
    yield;
    console.log('A: 步骤 3');
}

function* taskB() {
    console.log('B: 步骤 1');
    yield;
    console.log('B: 步骤 2');
}

function scheduler(tasks) {
    const gens = tasks.map(t => t());
    
    while (gens.length > 0) {
        const gen = gens.shift();
        const { done } = gen.next();
        if (!done) {
            gens.push(gen); // 未完成的任务重新入队
        }
    }
}

scheduler([taskA, taskB]);
// A: 步骤 1
// B: 步骤 1
// A: 步骤 2
// B: 步骤 2
// A: 步骤 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 12.3.5 生成器实现 async/await

async/await 的底层原理就是生成器 + Promise 的自动执行器:

// async/await 的等价实现
function spawn(generatorFn) {
    return function(...args) {
        const gen = generatorFn.apply(this, args);
        
        return new Promise((resolve, reject) => {
            function step(method, arg) {
                let result;
                try {
                    result = gen[method](arg);
                } catch (e) {
                    return reject(e);
                }
                
                if (result.done) {
                    return resolve(result.value);
                }
                
                Promise.resolve(result.value).then(
                    value => step('next', value),
                    err => step('throw', err)
                );
            }
            
            step('next', undefined);
        });
    };
}

// 用生成器写异步代码
const fetchUser = spawn(function* (id) {
    const response = yield fetch(`/api/users/${id}`);
    const data = yield response.json();
    return data;
});

// 等价于
async function fetchUserAsync(id) {
    const response = await fetch(`/api/users/${id}`);
    const data = await response.json();
    return data;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

# 12.4 异步迭代器

# 12.4.1 异步迭代协议

ES2018 引入了异步迭代协议,next() 方法返回 Promise:

// 异步可迭代对象实现 [Symbol.asyncIterator]()
const asyncRange = {
    from: 1,
    to: 5,
    
    [Symbol.asyncIterator]() {
        let current = this.from;
        const last = this.to;
        
        return {
            async next() {
                // 模拟异步操作
                await new Promise(r => setTimeout(r, 100));
                
                if (current <= last) {
                    return { value: current++, done: false };
                }
                return { value: undefined, done: true };
            }
        };
    }
};

// 用 for-await-of 遍历
async function main() {
    for await (const num of asyncRange) {
        console.log(num); // 1, 2, 3, 4, 5(每个间隔 100ms)
    }
}
main();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 12.4.2 异步生成器

异步生成器结合了 async 和 function*:

async function* fetchPages(baseUrl, totalPages) {
    for (let page = 1; page <= totalPages; page++) {
        const response = await fetch(`${baseUrl}?page=${page}`);
        const data = await response.json();
        yield data;
    }
}

// 使用
async function processAllPages() {
    for await (const pageData of fetchPages('/api/items', 5)) {
        console.log('Processing page:', pageData);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 12.4.3 流式数据处理

异步迭代器非常适合处理流式数据:

// 读取 ReadableStream
async function* readStream(stream) {
    const reader = stream.getReader();
    try {
        while (true) {
            const { done, value } = await reader.read();
            if (done) break;
            yield value;
        }
    } finally {
        reader.releaseLock();
    }
}

// 逐行读取文本流
async function* readLines(stream) {
    let buffer = '';
    const decoder = new TextDecoder();
    
    for await (const chunk of readStream(stream)) {
        buffer += decoder.decode(chunk, { stream: true });
        const lines = buffer.split('\n');
        buffer = lines.pop(); // 最后一段可能不完整
        
        for (const line of lines) {
            yield line;
        }
    }
    
    if (buffer) yield buffer; // 最后的剩余
}

// SSE (Server-Sent Events) 处理
async function* parseSSE(response) {
    for await (const line of readLines(response.body)) {
        if (line.startsWith('data: ')) {
            const data = line.slice(6);
            if (data === '[DONE]') return;
            yield JSON.parse(data);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

# 12.4.4 并发控制

结合异步迭代器实现并发控制:

async function* asyncPool(concurrency, iterable, fn) {
    const executing = new Set();
    
    for (const item of iterable) {
        const promise = fn(item).then(result => {
            executing.delete(promise);
            return result;
        });
        executing.add(promise);
        
        if (executing.size >= concurrency) {
            yield await Promise.race(executing);
        }
    }
    
    while (executing.size > 0) {
        yield await Promise.race(executing);
    }
}

// 使用:同时最多 3 个并发请求
const urls = ['/api/1', '/api/2', '/api/3', '/api/4', '/api/5'];

async function main() {
    for await (const result of asyncPool(3, urls, url => fetch(url))) {
        console.log('Got response:', result.status);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 12.5 内置可迭代对象详解

# 12.5.1 Array 迭代器

const arr = ['a', 'b', 'c'];

// values() - 值迭代器(默认)
for (const val of arr.values()) { /* 'a', 'b', 'c' */ }

// keys() - 键迭代器
for (const key of arr.keys()) { /* 0, 1, 2 */ }

// entries() - 键值对迭代器
for (const [i, val] of arr.entries()) {
    console.log(i, val); // 0 'a', 1 'b', 2 'c'
}

// arr[Symbol.iterator] === arr.values
console.log(arr[Symbol.iterator] === arr.values); // true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 12.5.2 Map 和 Set 迭代器

const map = new Map([['a', 1], ['b', 2]]);

// Map 默认迭代 entries
for (const [key, value] of map) {
    console.log(key, value); // 'a' 1, 'b' 2
}

// Map 的迭代顺序 = 插入顺序
map.keys();    // MapIterator {'a', 'b'}
map.values();  // MapIterator {1, 2}
map.entries(); // MapIterator {['a', 1], ['b', 2]}

const set = new Set([1, 2, 3]);
// Set 的 values() 和 keys() 相同
for (const val of set) {
    console.log(val); // 1, 2, 3
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 12.5.3 String 迭代器

const str = 'A😀B';

// for...of 正确处理 Unicode
for (const char of str) {
    console.log(char); // 'A', '😀', 'B'(3次,非4次)
}

// 对比 for 循环
for (let i = 0; i < str.length; i++) {
    console.log(str[i]); // 'A', '�', '�', 'B'(4次,emoji 被拆开)
}
1
2
3
4
5
6
7
8
9
10
11

# 12.5.4 arguments 和 NodeList

// arguments 是可迭代的
function test() {
    for (const arg of arguments) {
        console.log(arg);
    }
}

// NodeList 也是可迭代的
const divs = document.querySelectorAll('div');
for (const div of divs) {
    console.log(div.textContent);
}
1
2
3
4
5
6
7
8
9
10
11
12

# 12.6 迭代器工具库

实际开发中常用的迭代器工具函数:

// 组合多个可迭代对象
function* chain(...iterables) {
    for (const iterable of iterables) {
        yield* iterable;
    }
}
console.log([...chain([1, 2], [3, 4], [5])]); // [1, 2, 3, 4, 5]

// 压缩两个可迭代对象
function* zip(...iterables) {
    const iterators = iterables.map(i => i[Symbol.iterator]());
    
    while (true) {
        const results = iterators.map(it => it.next());
        if (results.some(r => r.done)) return;
        yield results.map(r => r.value);
    }
}
console.log([...zip([1, 2, 3], ['a', 'b', 'c'])]);
// [[1, 'a'], [2, 'b'], [3, 'c']]

// 枚举(带索引)
function* enumerate(iterable, start = 0) {
    let i = start;
    for (const value of iterable) {
        yield [i++, value];
    }
}
for (const [i, v] of enumerate(['a', 'b', 'c'])) {
    console.log(i, v); // 0 'a', 1 'b', 2 'c'
}

// 分块
function* chunk(iterable, size) {
    let batch = [];
    for (const item of iterable) {
        batch.push(item);
        if (batch.length === size) {
            yield batch;
            batch = [];
        }
    }
    if (batch.length > 0) yield batch;
}
console.log([...chunk([1,2,3,4,5], 2)]);
// [[1,2], [3,4], [5]]

// 扁平化
function* flatten(iterable, depth = 1) {
    for (const item of iterable) {
        if (depth > 0 && item[Symbol.iterator] && typeof item !== 'string') {
            yield* flatten(item, depth - 1);
        } else {
            yield item;
        }
    }
}
console.log([...flatten([[1, [2]], [3, [4, [5]]]], Infinity)]);
// [1, 2, 3, 4, 5]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

# 12.7 生成器与迭代器对比

特性 手动迭代器 生成器
语法复杂度 高(手动管理状态) 低(yield 自动管理)
可读性 较差 好(线性代码流)
return() 支持 需手动实现 自动支持(通过 finally)
内存效率 相同 相同(都是惰性求值)
双向通信 不支持 支持(next(value))
委托 手动实现 yield* 语法
调试 困难 可在 yield 处断点

建议:大多数场景优先使用生成器,除非需要极致的性能优化或在不支持生成器的环境中。

上次更新: 2026/06/10, 11:13:41
字符串处理
Symbol

← 字符串处理 Symbol→

最近更新
01
信号崩溃快速排查
06-15
02
CoreDump破案
06-15
03
perf火焰图实战
06-15
更多文章>
Theme by Vdoing | Copyright © 2019-2026 杨充 | MIT License | 桂ICP备2024034950号 | 桂公网安备45142202000030
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式