[ES6]---迭代器与生成器的用法

本文介绍了ES6中迭代器与生成器的概念与用法,包括Symbol类型、迭代器的实现方式及其与for...of语句的关系,以及生成器函数的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

迭代器与生成器

Symbol

Symbol是什么

ES6新增了第六种原始类型Symbol类型。Symbol类型是唯一的并且是不可修改的,也可以用来作为Object的key值

Symbol类型的变量是通过调用Symbol()函数生成的

let symbol = Symbol();
console.log(typeof symbol) //symbol
let symbol2 = Symbol('林俊杰')
console.log(symbol2) //Symbol(林俊杰)
let symbol3 = Symbol(6)
console.log(symbol3) //Symbol(6)

//可以改变变量值,但是不可以该类型
symbol3 = Symbol("ljj")
console.log(symbol3) //Symbol(ljj)
Symbol的方法
  • Symbol.for()方法
    • 作用 - 从symbol类型中查找指定的key
      • 如果存在这个key的话,返回
      • 如果不存在这个key的话,创建
  • Symbol.keyfor()方法
    • 用于获取symbol注册表中与某个symbol关联的键。
let symbol = Symbol.for('foo') //创建
console.log(symbol)
let result = Symbol.for('for') //查找
console.log(result)
Symbol与for…in

Symbols在 for …in迭代中不可枚举。另外,Object.getOwnPropertyNames()不会返回symbol对象的属性,但是可以使用Obiect.getOwnPropertySymbols()得到它们。

var obj = {};
//使用Symbol作为对象的属性名出现,是不可枚举的
obj[Symbol( "a")]= "a" ;
obj[Symbol.for("b")]="b";
obj["c"] = "c";
obj.d = "d";
for (var i in obj) {
    console.log(i); // logs "c" and "d"
}

迭代器

迭代器是什么

为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署lterator接口,就可以完成遍历操作。

作用:

  • 为各种数据结构,提供一个统一的、简便的访问接口。
  • 使得数据结构的成员能够按某种次序排列。
  • ES6新增了for…of循环语句,用于遍历迭代器。
lterator接口

在JavaScript 中迭代器( lterator )是一个对象,该对象提供next()方法用于返回序列中的下一项。该方法返回包含done和 value 两个属性的对象。

  • 作用 - 用于返回序列中的下一项
  • 返回值 - 是一个对象
    • done属性 - 表示是否迭代完毕
      • false - 表示当前没有迭代完毕
      • true - 表示当前迭代完毕
    • value属性 - 表示当前迭代的值

我们可以测试一下

function fn(array) {
    var index = 0;
    return {
        next: function() {
            return index < array.length ? {
                done: false,
                value: array[index++]
            } : {
                done: true
            }
        }
    }
}
let arr = ['林俊杰', '周杰伦', '李荣浩']
let iterator = fn(arr)
console.log(iterator.next()) //{ done: false, value: '林俊杰' }
console.log(iterator.next()) //{ done: false, value: '周杰伦' }
console.log(iterator.next()) //{ done: false, value: '李荣浩' }
console.log(iterator.next()) //{ done: true }
for…of语句的用法

遍历数组

// 遍历数组
let arr = [1, 2, 3, 4, 5];
for (let attr of arr) {
    // attr得到的是数组的元素内容
    console.log(attr); //1 2 3 4 5
}

遍历Set集合

let arr = [1, 2, 3, 4, 5];
let set = new Set(arr);
for (let attr of set) {
    // attr得到的是Set的元素内容
    console.log(attr); //1 2 3 4 5
}

遍历map集合

// 遍历map集合
let map = new Map()
let num = 100,
    str = "林俊杰",
    fun = function() {},
    obj = {};

map.set("num", num);
map.set("str", str);
map.set("fun", fun);
map.set("obj", obj);

for (let attr of map) {
    // attr得到的是Map的[key,value]键值对数组
    console.log(attr); //[ 'num', 100 ] [ 'str', '林俊杰' ] [ 'fun', [Function: fun] ] [ 'obj', {} ]
}
与for…in语句的区别
  • for…in不仅遍历自身,还会遍历手动添加的,甚至包括原型链的。
  • 如果用于遍历数组的话,遍历得到的键名为字符串类型的数字值。

下面我们来测试一下 for…in 和for…of有什么区别

Object.prototype.objCustom = function() {}
Array.prototype.arrCustom = function() {}

let iterable = [3, 5, 7]
iterable.foo = 'hello'

for (let i in iterable) {
    console.log(i) //0 1 2 foo arrCustom objCustom
}

for (let i of iterable) {
    console.log(i) //3 5 7
}

生成器

Generator函数是什么

虽然可以自定义一个迭代器,但自定义的迭代器需要显式地维护其内部状态。而生成器提供了另一个强大的选择,其提供了允许定义一个包含自有迭代算法的函数,同时可以自动维护其内部状态。Generator函数可以作为生成一个迭代器的特殊函数,该函数被调用时返回一个 Generator对象,该对象是符合可迭代协议和迭代器协议的。

Generator函数与普通函数的区别在于:

  • function*这种声明方式会定义一个生成器函数,它返回一个 Generator对象。
  • yield关键字用来暂停和恢复一个生成器函数。

定义生成器函数,

function* functionName(){yield关键字}

生成器函数在调用时,返回一个Generator对象。

function*表达式

function*这种声明方式( function关键字后跟一个星号)会定义一个生成器函数(Generatorfunction ),它返回一个 Generator 对象。

生成器函数在执行时能暂停,后面又能从暂停处继续执行。

function* fn() {}
let result = fn()
console.log(result) //Object [Generator] {}
yield表达式

用来暂停和恢复一个生成器函数。

// 定义一个生成器函数
function* fn() {
        let arr = ["林俊杰", "周杰伦", "李荣浩"];
        for (let i = 0; i < arr.length; i++) {
            yield arr[i];
        }
    }
    // 生成器函数调用返回生成器对象
let generator = fn();
// 生成器对象就是ES6提供的迭代器
console.log(generator.next()); // { value: '林俊杰', done: false }
console.log(generator.next()); // { value: '周杰伦', done: false }
console.log(generator.next()); // { value: '李荣浩', done: false }
console.log(generator.next()); // { value: 'undefined', done: true }
yield*表达式

yield*表达式用于委托给另一个Generator或可迭代对象.

function* g1() {
    yield 2;
    yield 3;
}
function* g2() {
    yield 1;
    yield* g1();
    yield 4;
}
// 生成器函数调用返回生成器对象
let generator = g2();
// 生成器对象就是ES6提供的迭代器
console.log(generator.next()); // { value: 1, done: false }
console.log(generator.next()); // { value: 2, done: false }
console.log(generator.next()); // { value: 3, done: false }
console.log(generator.next()); // { value: 4, done: false }
console.log(generator.next()); // { value: undefined, done: true }
Generator对象的方法
方法名称描述
next()方法返回一个包含属性done和value 的对象。该方法也可以通过接受一个参数用以向生成器传值
return()方法返回给定的值并结束生成器
throw()方法用于向生成器抛出异常,并恢复生成器的执行,返回带有done及 value两个属性的对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值