首页 > 编程语言 >JavaScript中的迭代器和生成器

JavaScript中的迭代器和生成器

时间:2024-11-17 22:44:23浏览次数:3  
标签:console log 迭代 JavaScript 生成器 value next done

迭代器和生成器

迭代器

在JavaScript中迭代器是一个对象,它是一个使用了next()方法实现了迭代器协议的的对象(方法名是约定的,必须是next,不能是其他的)。JavaScript中可以使用迭代器的常见对象有Array、Map、Set、String。我们可以通过Symbol.iterator属性获取当前实例的迭代器对象,如果存在的话。

这个next()方法每次返回一个对象,其中包含两个值:

value:表示当前迭代返回对象的值

done:表示迭代是否完成

const arr = [true, 2, 3, 4, 5];

const iter = arr[Symbol.iterator]();

console.log(typeof iter.next().value);
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());// 输出undefined和true,表示数组已经迭代完毕

迭代器一旦创建就可以显示的调用next方法完成迭代。迭代一个迭代器被称为消耗了这个迭代器,因为它通常只能执行一次。这意味着,每执行一次for…of都会创建一个新的迭代器对象

下面我们实现一个简单的迭代器。

function makeRangeIterator(start = 0, end = Infinity, step = 1) {
    let nextIndex = start; // 外部变量
    let iterationCount = 0;// 外部变量

    const rangeIterator = {
        a() {
            let result;
            if (nextIndex < end) {
                result = { value: nextIndex, done: false };
                nextIndex += step;
                iterationCount++;
                return result;
            }
            return { value: undefined, done: true };
        },
    };
    return rangeIterator;
}

const iter = makeRangeIterator(1, 5, 1);

console.log(iter.a());// { value: 1, done: false }
console.log(iter.a());// { value: 2, done: false }
console.log(iter.a());// { value: 3, done: false }
console.log(iter.a());// { value: 4, done: false }
console.log(iter.a());// { value: undefined, done: true }

疑问点

有人可能会问不是说代表next()方法不能变吗,为什么这里方法名是a,却能正常运行。这是因为这是手动迭代,要是使用for…of就会报错,因为for...of只认可名为next()的方法

还有人可能会疑问为什么nextIndex和iterationCount这两个变量能够一直被a方法访问,它们不应该在const iter = makeRangeIterator(1, 5, 1);这段代码执行完毕就不能被访问了吗,这里涉及到JavaScript的另外一个高级特性——闭包,不了解的伙伴可以移步本栏目下关于JavaScript的函数,了解这一特性。

可迭代对象

JavaScript中的可迭代对象要求对象本身或者对象的原型链实现了名为Symbol.iterator方法,且该方法返回一个迭代器对象

我们可以通过Symbol.iterator属性去获取实现了迭代器的对象的迭代器对象。

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const iter = arr[Symbol.iterator]();

let done = false;

do {
    const { value, done: Done } = iter.next();
    done = Done;
    console.log(value);
} while (!done);

在以上代码中,我们获取了arr的迭代器对象,并完成了对arr的手动迭代。

下面我们手动实现一个可迭代对象。我们创建一个名为makeRangeIterator的函数,它会返回一个名为rangeIterator的可迭代对象,这个对象使用括号语法成功拥有了名为Symbol.iterator的方法。而这个方法又返回了一个实现了next()方法的迭代器对象。最后我们使用for…of完成了迭代。

function makeRangeIterator(start = 0, end = Infinity, step = 1) {
    let nextIndex = start;
    let iterationCount = 0;

    const rangeIterator = {
        [Symbol.iterator]() {
            return {
                next() {
                    let result;
                    if (nextIndex < end) {
                        result = { value: nextIndex, done: false };
                        nextIndex += step;
                        iterationCount++;
                        return result;
                    }
                    return { value: undefined, done: true };
                },
            };
        },

    };
    return rangeIterator;
}

const iter = makeRangeIterator(1, 5, 1);

// 使用 for...of 循环
for (const value of iter) {
    console.log(value); // 1, 2, 3, 4
}

一些语句和表达式专用于可迭代对象,例如 for…of 循环、展开语法yield*解构语法。

for (let value of ["a", "b", "c"]) {
  console.log(value);
}
// "a"
// "b"
// "c"

[..."abc"]; // ["a", "b", "c"]

function* gen() {
  yield* ["a", "b", "c"];
}

gen().next(); // { value: "a", done: false }

[a, b, c] = new Set(["a", "b", "c"]);
a; // "a"

生成器

生成器是一个函数,它允许你定义一个非连续执行的函数作为迭代算法。由function *语法和yield关键字组成的函数就是生成器函数。调用生成器函数之后会返回一个Generator对象,这个对象是实现了迭代器协议可迭代协议的迭代器对象。

function *:用于定义生成器函数。当调用生成器函数时,它不会立即执行函数体内的代码,而是返回一个 Generator 对象。可以通过 next() 方法逐步执行生成器函数体内的代码。

yield

  • 暂停执行:yield表达式用于在生成器函数体内暂停执行,并返回一个值。每次调用 next()方法时,生成器函数会从上次暂停的地方继续执行,直到遇到下一个 yield表达式或函数结束(return值)
  • 返回值和状态:表达式返回一个对象,包含两个属性:
    • value:当前迭代的值。
    • done:布尔值,表示迭代是否完成。
function* makeRangeGenerator(start = 0, end = Infinity, step = 1) {
    let nextIndex = start;
    while (nextIndex < end) {
        yield nextIndex;
        console.log("通过yield的暂停");
        nextIndex += step;
    }
}

const gen = makeRangeGenerator(1, 5, 1);

console.log(gen.next()); // { value: 1, done: false }	
console.log(gen.next()); // { value: 2, done: false } 通过yield的暂停
console.log(gen.next()); // { value: 3, done: false } 通过yield的暂停
console.log(gen.next()); // { value: 4, done: false } 通过yield的暂停
console.log(gen.next()); // { value: undefined, done: true } 通过yield的暂停

yield除了能够返回一个对象,还能接收Generator对象调用next()方法时传递的参数。

function* makeRangeGenerator(start = 0, end = Infinity, step = 1) {
    let nextIndex = start;
    while (nextIndex < end) {
        let increment = yield nextIndex;
        console.log("通过yield的暂停,接收到的参数:", increment);
        if (increment !== undefined) {
            step = increment;
        } else {
            step = 1;
        }
        nextIndex += step;
    }
}

const gen = makeRangeGenerator(1, 20, 1);

console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next(2)); // { value: 3, done: false } (1 + 2)
console.log(gen.next()); // { value: 4, done: false } (3 + 1)
console.log(gen.next()); // { value: undefined, done: true } (4 + 1 >= 5)
function* makeRangeGenerator(start = 0, end = Infinity, step = 1) {
    let nextIndex = start;
    while (nextIndex < end) {
        let increment = yield nextIndex;
        console.log("通过yield的暂停,接收到的参数:", increment);
        if (increment === 4) {
            console.log("你传入了禁忌参数,导致生成器提前中止", increment);
            return;
        } else if (increment !== undefined) {
            step = increment;
        } else {
            step = 1;
        }
        nextIndex += step;
    }
}

const gen = makeRangeGenerator(1, 20, 1);

console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next(2)); // { value: 3, done: false } (1 + 2)
console.log(gen.next(4)); // { value: undefined, done: true } 提前中止

生成器在 JavaScript 中有多种使用场景,它们提供了一种强大的方式来处理异步操作、生成大量数据、以及实现复杂的迭代逻辑。

标签:console,log,迭代,JavaScript,生成器,value,next,done
From: https://blog.csdn.net/weixin_62652659/article/details/143829201

相关文章

  • Python基础:探索迭代器(Iterator)的奥秘
    引言在当今的科技时代,Python作为一种功能强大且广泛应用的编程语言,在数据处理、人工智能、网络爬虫等诸多领域发挥着不可替代的作用。迭代器作为Python中的一个重要概念,对于高效处理数据、优化算法等有着极大的意义。它能够以一种简洁而有效的方式遍历数据结构,无论是大型数......
  • 【全栈开发(TypeOrm-Javascript)学习笔记三】
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、EntityManager二、Repository三、Find选项四、自定义Repository五、EntityManagerAPI六、RepositoryAPI总结前言本章节主要了解typeOrm框架EntityManager和Repository,学习常见的s......
  • 【C++】深入理解自定义 list 容器中的 list_iterator:迭代器实现详解
    个人主页:起名字真南的CSDN博客个人专栏:【数据结构初阶】......
  • Cangjie_仓颉编程-迭代器
    Python迭代器遍历一个集合迭代器和for循环for(leti=0;i<arr.length;i++)其中最主要的差别就是:是否通过索引来访问集合forin迭代协议是指对象必须实现两个特殊的方法,即__iter__()和next(),以便能支持迭代操作Cangjie迭代器Iterator<T> 该类表示迭代器......
  • 小红书加微引导图生成器:轻松创建吸引人的微信号分享图
    大家好!今天我要向你们介绍一个超级实用的小工具——小红书加微引导图生成器。如果你经常在小红书上分享内容,想要吸引更多粉丝添加你的微信,这个工具绝对是你的得力助手!为什么需要这个工具?我们都知道,小红书对聊天中的文字审核非常严格。直接发送微信号可能会被系统拦截,影......
  • JavaScript判断用户设备类型:PC端与移动端的区分方法
    在JavaScript中,可以通过检查用户代理字符串(UserAgentString)来判断用户设备类型,即访问网站的是PC端还是移动端设备。用户代理字符串是浏览器在发送HTTP请求时附带的一段信息,它包含了浏览器类型、版本、操作系统以及设备类型等信息。以下是一个简单的示例代码,用于判断用户......
  • 前端必知必会-JavaScript if、else 和 else if
    文章目录JavaScriptif、else和elseif条件语句if语句else语句elseif语句总结JavaScriptif、else和elseif条件语句用于根据不同的条件执行不同的操作。条件语句编写代码时,您经常希望针对不同的决策执行不同的操作。您可以在代码中使用条件语句来执行......
  • 前端必知必会-JavaScript Switch 语句
    文章目录JavaScriptSwitch语句JavaScriptSwitch语句break关键字default关键字常见代码块switch详细信息严格比较总结JavaScriptSwitch语句switch语句用于根据不同的条件执行不同的操作。JavaScriptSwitch语句使用switch语句从多个代码块中选择一个......
  • javaScript交互补充3(JSON数据)
    3.1、JSON(1)、定义:JSON数据格式JavaScriptObjectNotation缩写即js对象表示法由于JS中的对象只有JS自己认识,其他的语言都不认识,所以引入了JSON,JSON就是一个特殊格式的字符串,这个字符串可以被任意的语言所识别,并且可以转换为任意语言中的对象,JSON在开发中主要用来数据的......
  • javaScript交互补充4(本地存储)
    localstorage、Sessionstorage是WebStorage,H5的本地存储机制。是本地存储,存储在客户端,以键/值对的形式存储的,通常以字符串存储。是针对HTML4中Cookie存储机制的一个改善,由于Cookie存储机制有很多缺点,HTML5不再使用它,转而使用改良后的WebStorage存储机制。4.1、Cookie(1......