JavaScript中的生成器函数详解

在 JavaScript 中,生成器函数 Generator Function 是一种特殊的函数,它允许你在函数执行过程中暂停和恢复。生成器函数通过 function* 语法定义,并使用 yield 关键字来控制函数的执行流程。生成器函数返回一个生成器对象,该对象遵循迭代器协议,可以逐步生成值。

以下是生成器函数的详细解析:

1. 基本语法

生成器函数使用 function* 定义,函数体内可以使用 yield 关键字来暂停函数的执行并返回一个值。

function* myGenerator() {
    yield 1;
    yield 2;
    yield 3;
}

function*:定义生成器函数的关键字。

yield:暂停函数执行并返回一个值。每次调用生成器对象的 next() 方法时,函数会从上次暂停的地方继续执行。

2. 生成器对象

生成器函数调用时不会立即执行函数体,而是返回一个生成器对象。这个生成器对象是一个迭代器,可以通过 next() 方法逐步执行生成器函数。

const gen = myGenerator();

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 }

next():恢复生成器函数的执行,直到遇到下一个 yield 或函数结束。

返回一个对象,包含两个属性:

value:yield 表达式的值。

done:布尔值,表示生成器函数是否已经执行完毕。

3. yield 关键字

yield 是生成器函数的核心关键字,它的作用如下:

1. 暂停函数执行:当生成器函数执行到 yield 时,会暂停执行并返回 yield 后面的值;

2. 恢复函数执行:当调用生成器对象的 next() 方法时,函数会从上次暂停的地方继续执行,直到遇到下一个 yield 或函数结束;

function* myGenerator() {
    yield "Hello";
    yield "World";
}

const gen = myGenerator();

console.log(gen.next().value); // 'Hello'
console.log(gen.next().value); // 'World'
console.log(gen.next().done);  // true

4. yield* 表达式

yield* 用于委托给另一个生成器或可迭代对象(如数组、字符串等)。它允许在一个生成器函数中调用另一个生成器函数。

function* generator1() {
    yield 1;
    yield 2;
}

function* generator2() {
    yield* generator1(); // 委托给 generator1
    yield 3;
}

const gen = generator2();

console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
console.log(gen.next().done); // true

5. 生成器函数的特性

5.1. 惰性求值

生成器函数是惰性的,只有在调用 next() 时才会执行。这使得生成器非常适合处理大量数据或无限序列。

function* infiniteSequence() {
    let i = 0;
    while (true) {
        yield i++;
    }
}

const gen = infiniteSequence();

console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
// 可以无限调用

5.2. 双向通信

生成器函数不仅可以通过 yield 返回值,还可以通过 next() 方法接收外部传入的值。

function* generator() {
    const x = yield "Hello";
    yield x;
}

const gen = generator();

console.log(gen.next().value); // 'Hello'
console.log(gen.next(42).value); // 42

第一次调用 next() 时,生成器函数执行到 yield 'Hello' 并暂停。

第二次调用 next(42) 时,42 会作为 yield 表达式的值传入,生成器函数继续执行。

5.3. 提前终止

生成器对象提供了 return() 和 throw() 方法,可以提前终止生成器函数的执行。

return(value):终止生成器函数并返回指定的值。

throw(error):在生成器函数内部抛出一个错误。

function* generator() {
    yield 1;
    yield 2;
    yield 3;
}

const gen = generator();

console.log(gen.next().value); // 1
console.log(gen.return(42).value); // 42
console.log(gen.next().done); // true

6. 生成器函数的应用场景

6.1. 惰性求值

生成器函数非常适合处理大量数据或无限序列,因为它只在需要时生成值。

function* fibonacci() {
    let [prev, curr] = [0, 1];
    while (true) {
        yield curr;
        [prev, curr] = [curr, prev + curr];
    }
}

const fib = fibonacci();

console.log(fib.next().value); // 1
console.log(fib.next().value); // 1
console.log(fib.next().value); // 2
console.log(fib.next().value); // 3
console.log(fib.next().value); // 5

6.2. 异步编程

在 async/await 出现之前,生成器函数常用于简化异步编程。通过结合 Promise 和生成器,可以实现类似于 async/await 的效果。

function* asyncGenerator() {
    const result1 = yield new Promise((resolve) =>
        setTimeout(() => resolve(1), 1000)
    );
    const result2 = yield new Promise((resolve) =>
        setTimeout(() => resolve(2), 1000)
    );
    return result1 + result2;
}

function runGenerator(generator) {
    const gen = generator();

    function handle(result) {
        if (result.done) return Promise.resolve(result.value);
        return Promise.resolve(result.value).then((res) => {
            return handle(gen.next(res));
        });
    }

    return handle(gen.next());
}

runGenerator(asyncGenerator).then(console.log); // 3

6.3. 自定义迭代器

生成器函数可以用于创建自定义迭代器,简化迭代器的实现。

const myIterable = {
    *[Symbol.iterator]() {
        yield 1;
        yield 2;
        yield 3;
    },
};

for (const value of myIterable) {
    console.log(value); // 1, 2, 3
}

7. 总结

1. 生成器函数使用 function* 定义,通过 yield 暂停和恢复执行;

2. 生成器函数返回一个生成器对象,该对象是一个迭代器,可以通过 next() 方法逐步执行;

3. yield* 用于委托给另一个生成器或可迭代对象;

4. 生成器函数适用于惰性求值、异步编程和自定义迭代器等场景;

生成器函数提供了一种强大的控制流机制,使得你可以更灵活地管理函数的执行过程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

艾光远

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值