资讯专栏INFORMATION COLUMN

【ES6脚丫系列】遍历器iterator

keke / 3280人阅读

摘要:就称为部署了遍历器接口。是一个函数,调用它会生成一个遍历器对象。它的属性,也是一个遍历器对象生成函数,执行后返回它自己。返回遍历器对象。下面是一个无限运行的遍历器对象的例子。

『ES6知识点总结』遍历器iterator
本文内容如下:

1 具有iterator接口的数据结构
2 遍历器过程
3 遍历器作用:
4 模拟next()方法
5 使用while循环
6 TypeScript的写法
7 Iterator接口与Generator函数
8 对象的遍历器接口
8.1 对于类似数组的对象
9 调用Iterator接口的场合
9.1 解构赋值
9.2 扩展运算符
9.3 yield*
9.4 其他场合
10 字符串的Iterator接口
具有iterator接口的数据结构

【01】原生就具有Iterator接口,它们的遍历器接口部署在Symbol.iterator属性上:

Array,Object(类数组对象),Map,WeakMap,Set,WeakSet,字符串。

let arr = new Array();

let iterator =arr[Symbol.iterator]();

【02】其他数据结构(主要是对象)的Iterator接口,都需要自己部署在Symbol.iterator属性上面。(原型链上的对象具有该方法也可)。

【03】一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”(iterable)。
就称为部署了遍历器接口。就可以遍历所有成员。可通过for of 遍历。

【04】遍历器对象本身也有Symbol.iterator方法,执行后返回自身。

gen是一个Generator函数,调用它会生成一个遍历器对象g。它的Symbol.iterator属性,也是一个遍历器对象生成函数,执行后返回它自己。

function* gen(){ // some code
}
var g = gen();

g[Symbol.iterator]() === g // true
遍历器过程

【01】zyx456:说白了,等于这些数据结构有一个方法(PS,这个方法称为遍历器函数)。

方法名是[Symbol.iterator],方法中返回一个对象(PS,这个对象称为遍历器对象),该对象有一个next()方法。这个next()会遍历数据结构的成员。返回{value:XX||undefined , done:true||false}

let obj = {

​ [Symbo.iterator] (){

return {next(){}}

}

}

调用遍历器函数,就会返回一个遍历器对象。

每次调用iterator.next(),就使用该数据结构的一个成员,成员的值就是返回对象中value的值。done为false,最后会返回一个有value和done两个属性的对象。

从头到尾依次使用数据结构的成员。直到使用的成员都访问完了。

当数据结构的成员已全部访问了,此时,再调用iterator.next()。返回的对象中,value的值为undefined,done为true。

done属性是一个布尔值,表示遍历是否结束。

let arr = [1,2,3];

let iterator = arr[Symbol.iterator]();

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

let arr = ["a", "b", "c"];
let iter = arr[Symbol.iterator]();//返回遍历器对象。

iter.next() // { value: "a", done: false }
iter.next() // { value: "b", done: false }
iter.next() // { value: "c", done: false }
iter.next() // { value: undefined, done: true }

【03】遍历器与它所遍历的那个数据结构是分开的。

遍历器作用:

一是为各种数据结构提供一个统一的访问接口;

二是让数据结构的成员可以按某种次序排列;

三是供for...of使用。

模拟next()方法

使用一个函数,函数参数是数组,返回一个对象,对象具有next()方法。

在next()中,使用一个变量,遍历数组的下标。通过和数组的长度对比,来判断返回不同的对象。

返回对象都有value和done属性。

function Convert(arr){
    let index = 0;
    return {
        next (){
            if(index

zyx456:next返回的就是指针对象了。此时,it是对象,它的变量index是保存在函数中的。

对于遍历器对象来说,done: false和value: undefined属性都是可以省略的,因此上面的Covert函数可以简写成下面的形式。

function Covert(array) {    var nextIndex = 0;
    return {
        next: function() {
            return nextIndex < array.length ? { value: array[nextIndex++] } : { done: true }; }
    }
}

【】下面是一个无限运行的遍历器对象的例子。

zyx456:仅了解。实用性不大。

遍历器生成函数idMaker,返回一个遍历器对象(即指针对象)。但是并没有对应的数据结构,或者说,遍历器对象自己描述了一个数据结构出来。

function idMaker() {
    let index = 0;
    return {
        next: function() {
            return { value: index++, done: false }; }
    }
}var it = idMaker();

it.next().value // "0"
it.next().value // "1"
it.next().value // "2"
    // ...
使用while循环

有了遍历器接口,数据结构就可以用for...of循环遍历,也可以使用while循环遍历。

var $iterator = ITERABLE[Symbol.iterator]();
var $result = $iterator.next();
while (!$result.done) {
    var x = $result.value; // ...
    $result = $iterator.next();
}
TypeScript的写法

遍历器接口(Iterable)、指针对象(Iterator)和next方法返回值的规格可以描述如下。

interface Iterable {
    [Symbol.iterator](): Iterator, }

interface Iterator { next(value ? : any): IterationResult, }

interface IterationResult {
    value: any,
        done: boolean,
}
Iterator接口与Generator函数
var myIterable = {};

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

// 或者采用下面的简洁写法
let obj = { * [Symbol.iterator]() {
        yield "hello";
        yield "world";
    }
};
for (let x of obj) {
    console.log(x);
}
// hello
// world
对象的遍历器接口

【】对象部署遍历器接口并不是很必要,可以使用Map。

对于类似数组的对象

(存在数值键名和length属性),部署Iterator接口,有一个简便方法,就是Symbol.iterator方法直接引用数组的Iterator接口。

NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
// 或者
NodeList.prototype[Symbol.iterator] = [][Symbol.iterator];
[...document.querySelectorAll("div")] // 可以执行了

下面是类似数组的对象调用数组的Symbol.iterator方法的例子。

let iterable = {
    0: "a",
    1: "b",
    2: "c",
    length: 3,
    [Symbol.iterator]: Array.prototype[Symbol.iterator]
};
for (let item of iterable) {
    console.log(item); // "a", "b", "c"
}
调用Iterator接口的场合

有一些场合会默认调用Iterator接口(即Symbol.iterator方法)。

解构赋值

对数组和Set结构进行解构赋值时,会默认调用Symbol.iterator方法。

let set = new Set().add("a").add("b").add("c");
let [x, y] = set;
// x="a"; y="b"
let [first, ...rest] = set;
// first="a"; rest=["b","c"];
扩展运算符

扩展运算符(...)会内部调用默认的iterator接口。

可以将任何部署了Iterator接口的数据结构,转为数组。

// 例一
var str = "hello";
[...str] //  ["h","e","l","l","o"]

// 例二
let arr = ["b", "c"];
["a", ...arr, "d"]
// ["a", "b", "c", "d"]
let arr = [...iterable];
yield*

yield*后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口。

let generator = function* () {
  yield 1;
  yield* [2,3,4];
  yield 5;};var iterator = generator();

iterator.next() // { value: 1, done: false }
iterator.next() // { value: 2, done: false }
iterator.next() // { value: 3, done: false }
iterator.next() // { value: 4, done: false }
iterator.next() // { value: 5, done: false }
iterator.next() // { value: undefined, done: true }
其他场合

由于数组的遍历会调用遍历器接口,所以任何接受数组作为参数的场合,其实都调用了遍历器接口。

下面是一些例子。

for...of

Array.from()

Map(), Set(), WeakMap(), WeakSet()(比如new Map([["a",1],["b",2]]))

Promise.all([])

Promise.race([])

字符串的Iterator接口

字符串是一个类似数组的对象,原生具有Iterator接口。

var someString = "hi";
typeof someString[Symbol.iterator]    // "function"
var iterator = someString[Symbol.iterator]();
iterator.toString(); // => "[object String Iterator]"
iterator.next() // { value: "h", done: false }
iterator.next() // { value: "i", done: false }
iterator.next() // { value: undefined, done: true }
let some = "book";
for (let i of some){
    console.log(i)
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/105557.html

相关文章

  • ES6脚丫系列】Symbol

    摘要:它是语言的第七种数据类型,前六种是布尔值字符串数值对象。在中,根据属性名来进行判断。,是一个布尔值,表示该对象使用时,是否可以展开。等同于,指向该对象的默认遍历器方法,即该对象进行循环时,会调用这个方法,返回该对象的默认遍历器。 本文字数:3000+,阅读时间6分钟。 如果有理解不到位的地方,欢迎大家纠错。如果觉得还可以,希望大家可以点个赞。 谢谢大家。 目录 一、Symbol是什么...

    Flands 评论0 收藏0
  • ES6脚丫系列】Set+WeakSet+Map+WeakMap

    摘要:返回一个布尔值,表示该值是否为的成员。清除所有成员,没有返回值。返回的都是遍历器对象。结构的实例的方法,用于对每个成员执行某种操作,没有返回值。这个特点意味着,无法引用的成员,因此是不可遍历的。数组成员是一个或多个表示键值对的一维数组。 本文字数:4700+,阅读时间约10分钟。 如果有理解不到位的地方,欢迎大家纠错。 一、Set 【01】Set是一种数据结构。类似于数组,但是成员的值...

    lyning 评论0 收藏0
  • ES6脚丫系列】箭头函数

    摘要:箭头函数本文字符数,阅读时间约分钟左右。箭头函数等于说,只保留了函数的参数和返回。箭头函数体内的,继承的是外层代码块的。所以,不用用箭头函数声明对象的方法。不可以使用命令因此箭头函数不能用作函数。 【01】ES6箭头函数 本文字符数4300+,阅读时间约8分钟左右。 【01】箭头函数 等于说,只保留了函数的参数和返回。省略function和return。 写法: (形参) => {st...

    tinyq 评论0 收藏0
  • ES6脚丫系列】Promise

    摘要:三种状态进行中已完成,又称已失败。如果的状态是,那么的回调函数就会等待的状态改变,在此之前不会有结果。等价于例子例子的概念是实例的别名,用于指定发生错误时的回调函数。 『ES6知识点总结』变量的解构赋值 本文主要内容如下:1 Promise是什么?1.1 特点:1.2 三种状态:1.3 用处:1.4 Promise缺点:1.5 历史过程2 生成promise实例3 pr...

    BoYang 评论0 收藏0
  • ES6 系列之模拟实现一个 Set 数据结构

    摘要:基本介绍提供了新的数据结构。初始化本身是一个构造函数,用来生成数据结构。函数可以接受一个数组或者具有接口的其他数据结构作为参数,用来初始化。返回一个布尔值,表示该值是否为的成员。清除所有成员,无返回值。 基本介绍 ES6 提供了新的数据结构 Set。 它类似于数组,但是成员的值都是唯一的,没有重复的值。 初始化 Set 本身是一个构造函数,用来生成 Set 数据结构。 let set ...

    Backache 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<