Skip to content

对象、类与面向对象编程

迭代器与生成器

迭代器模式

1. 理解迭代器

迭代器模式提供了一种统一的方式来遍历不同的集合类型。在 JavaScript 中,迭代器是一个对象,它定义了一个标准的方式来产生一个值的序列。

javascript
// 基本迭代器协议
let iterator = {
    next() {
        return {
            value: any,
            done: boolean
        };
    }
};

// 可迭代协议
let iterable = {
    [Symbol.iterator]() {
        return iterator;
    }
};

2. 创建自定义迭代器

javascript
// 实现一个范围迭代器
class RangeIterator {
    constructor(start, end) {
        this.current = start;
        this.end = end;
    }

    [Symbol.iterator]() {
        return this;
    }

    next() {
        let value = this.current;
        if (value <= this.end) {
            this.current++;
            return { value, done: false };
        }
        return { done: true };
    }
}

// 使用范围迭代器
let range = new RangeIterator(1, 3);
for (let num of range) {
    console.log(num);  // 1, 2, 3
}

// 实现一个树结构迭代器
class TreeNode {
    constructor(value) {
        this.value = value;
        this.left = null;
        this.right = null;
    }

    *[Symbol.iterator]() {
        // 中序遍历
        if (this.left) yield* this.left;
        yield this.value;
        if (this.right) yield* this.right;
    }
}

// 使用树迭代器
let tree = new TreeNode(1);
tree.left = new TreeNode(2);
tree.right = new TreeNode(3);
for (let value of tree) {
    console.log(value);  // 2, 1, 3
}

3. 内置可迭代对象

javascript
// 数组迭代
let arr = ['a', 'b', 'c'];
let iterator = arr[Symbol.iterator]();
console.log(iterator.next());  // { value: 'a', done: false }
console.log(iterator.next());  // { value: 'b', done: false }
console.log(iterator.next());  // { value: 'c', done: false }
console.log(iterator.next());  // { value: undefined, done: true }

// Map迭代
let map = new Map([['name', 'John'], ['age', 30]]);
for (let [key, value] of map) {
    console.log(`${key}: ${value}`);
}

// Set迭代
let set = new Set(['red', 'green', 'blue']);
for (let color of set) {
    console.log(color);
}

生成器

1. 生成器基础

生成器是一种特殊的函数,可以在执行过程中暂停和恢复。

javascript
// 基本生成器
function* numberGenerator() {
    yield 1;
    yield 2;
    yield 3;
}

let gen = numberGenerator();
console.log(gen.next());  // { value: 1, done: false }
console.log(gen.next());  // { value: 2, done: false }
console.log(gen.next());  // { value: 3, done: false }
console.log(gen.next());  // { value: undefined, done: true }

// 带参数的生成器
function* dialogueGenerator() {
    const name = yield "What's your name?";
    const age = yield "How old are you?";
    return `Hello, ${name}! You are ${age} years old.`;
}

let dialogue = dialogueGenerator();
console.log(dialogue.next());          // { value: "What's your name?", done: false }
console.log(dialogue.next('John'));    // { value: "How old are you?", done: false }
console.log(dialogue.next('30'));      // { value: "Hello, John! You are 30 years old.", done: true }

2. 高级生成器模式

2.1 异步操作序列

javascript
// 模拟异步操作
function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

// 异步任务执行器
function* taskGenerator() {
    try {
        console.log('Starting tasks...');
        yield delay(1000);
        console.log('Task 1 completed');
        yield delay(1000);
        console.log('Task 2 completed');
        yield delay(1000);
        console.log('All tasks completed');
    } catch (err) {
        console.error('Task failed:', err);
    }
}

// 执行器函数
async function runGenerator(generator) {
    const iterator = generator();
    let result;
    do {
        result = await iterator.next();
    } while (!result.done);
    return result.value;
}

// 使用执行器
runGenerator(taskGenerator);

2.2 数据流处理

javascript
// 实现数据流管道
function* numberStream() {
    yield* [1, 2, 3, 4, 5];
}

function* filter(iterator, predicate) {
    for (const value of iterator) {
        if (predicate(value)) {
            yield value;
        }
    }
}

function* map(iterator, transform) {
    for (const value of iterator) {
        yield transform(value);
    }
}

// 使用管道处理数据
const pipeline = map(
    filter(numberStream(), n => n % 2 === 0),
    n => n * 2
);

for (const value of pipeline) {
    console.log(value);  // 4, 8
}

3. 实际应用场景

3.1 分页数据加载

javascript
class DataLoader {
    constructor(pageSize = 10) {
        this.pageSize = pageSize;
        this.currentPage = 0;
        this.data = [];
    }

    async loadPage() {
        // 模拟API调用
        const response = await fetch(`/api/data?page=${this.currentPage}&size=${this.pageSize}`);
        const data = await response.json();
        return data;
    }

    async *loadAll() {
        while (true) {
            const pageData = await this.loadPage();
            if (pageData.length === 0) break;
            
            this.currentPage++;
            yield* pageData;
        }
    }
}

// 使用示例
async function displayData() {
    const loader = new DataLoader();
    for await (const item of loader.loadAll()) {
        console.log(item);
    }
}

3.2 状态机实现

javascript
function* createStateMachine(states, initialState) {
    let currentState = initialState;
    
    while (true) {
        const action = yield currentState;
        const nextState = states[currentState][action];
        
        if (nextState) {
            currentState = nextState;
        } else {
            console.warn(`Invalid action "${action}" for state "${currentState}"`);
        }
    }
}

// 使用示例:交通信号灯
const trafficLightStates = {
    red: { next: 'green' },
    green: { next: 'yellow' },
    yellow: { next: 'red' }
};

const trafficLight = createStateMachine(trafficLightStates, 'red');
console.log(trafficLight.next().value);     // 'red'
console.log(trafficLight.next('next').value); // 'green'
console.log(trafficLight.next('next').value); // 'yellow'
console.log(trafficLight.next('next').value); // 'red'

迭代器与生成器的高级模式

1. 组合模式

javascript
// 组合多个迭代器
function* combine(...iterables) {
    for (const iterable of iterables) {
        yield* iterable;
    }
}

// 使用示例
const numbers = [1, 2, 3];
const letters = ['a', 'b', 'c'];
const combined = combine(numbers, letters);
console.log([...combined]);  // [1, 2, 3, 'a', 'b', 'c']

// 交替组合
function* alternate(...iterables) {
    const iterators = iterables.map(i => i[Symbol.iterator]());
    while (true) {
        const results = iterators.map(i => i.next());
        if (results.every(r => r.done)) break;
        yield* results.map(r => r.value).filter(v => v !== undefined);
    }
}

const alternated = alternate(numbers, letters);
console.log([...alternated]);  // [1, 'a', 2, 'b', 3, 'c']

2. 异步迭代器

javascript
// 实现异步迭代器
class AsyncNumberGenerator {
    constructor(start, end, delay = 1000) {
        this.start = start;
        this.end = end;
        this.delay = delay;
    }

    async *[Symbol.asyncIterator]() {
        for (let i = this.start; i <= this.end; i++) {
            await new Promise(resolve => setTimeout(resolve, this.delay));
            yield i;
        }
    }
}

// 使用异步迭代器
async function demo() {
    const numbers = new AsyncNumberGenerator(1, 3);
    for await (const num of numbers) {
        console.log(num);  // 每隔1秒输出:1, 2, 3
    }
}

最佳实践

  1. 迭代器使用建议

    • 使用生成器函数简化迭代器创建
    • 注意处理异常情况
    • 合理使用 return() 和 throw() 方法
  2. 生成器使用建议

    • 使用生成器处理大数据集
    • 实现异步操作序列
    • 注意内存管理
  3. 性能考虑

    • 避免无限迭代
    • 适当使用缓存
    • 考虑懒加载模式

注意事项

  • 迭代器状态是一次性的
  • 生成器函数的上下文会被保留
  • 注意处理异步操作的错误

练习题

  1. 实现一个斐波那契数列生成器。
  2. 创建一个支持过滤和转换的数据流管道。
  3. 实现一个异步任务队列,使用生成器控制执行流程。
  4. 设计一个分页数据加载器,使用异步迭代器实现。

扩展阅读

本站内容采用 "署名-非商业性使用-禁止演绎 4.0 国际许可协议" 进行许可