资讯专栏INFORMATION COLUMN

Introuction to JavaScript iterator

kviccn / 1150人阅读

Symbol

ES6 introcues a new type called symbol. The Symbol function returns a value of type symbol.

const symbol1 = Symbol();
const symbol2 = Symbol("hi");

console.log(typeof symbol1); //symbol

console.log(symbol3.toString()); //Symbol(foo)

// each symbol value created by Symbol function is unique
console.log(Symbol("foo") === Symbol("foo"));  // false

// Symbol itself is a function
console.log(typeof Symbol); //function
Iterator

An iterator is an object that provides a next method which returns the next item in the sequence. This method returns an object with two properties: done and value. For an object to be iterable, it must have a function property with a Symbol.iterator key, which returns a new iterator for each call.

// Array has build-in iteration support
functioin forOf(arr) {
    for(let i of arr) {
        console.log(i);
    }
}

/**
 * for...of loops is based on iterator
 * so forOf implementation above is basically:
 */
function iterating(arr) {
    let iterator = arr[Symbol.iterator](); //get the iterator for the array
    let next = iterator.next();
    while(!next.done) {
        console.log(next.value);
        next = iterator.next();
    }
}
Make Object iterable

Object doesn"t have build-in iteration support.

let obj = {a: "b", c: "d"}
for(let i of obj) {
    //Uncaught TypeError: obj is not iterable
    console.log(i);
}

To make Object iterable, we have to add Symbol.iterator, either to the instance or the prototype.

Object.defineProperty(Object.prototype, Symbol.iterator, {
    value: function() {
        let keys = Object.keys(this);
        let index = 0;
        return {
            next: () => {
                let key = keys[index++];
                return {
                    value: `${key}-${this[key]}`,
                    done: index > keys.length
                }
            }
        };
    },
    enumerable: false
});

let obj = {a: "b", c: "d"}
for(let i of obj) {
    console.log(i); // a-b c-d
}
Generator

The function declaration defines a generator function, whose return value is generator object. The generator object conforms to the iterator protocol. Note generator function* itself is a function.

//generator function
function* generatorFn() {
    yield 1;
    return 2;
}

// generator object - iterator
let generatorObj = generatorFn();
let nextItem = generatorObj.next(); 

console.log(typeof generatorFn); //function
console.log(typeof generatorObj); //object
console.log(typeof generatorObj.next); //function
console.log(nextItem); //{value: 1, done: false}

Therefore, to make Object iterable, we can define its Symbol.iterator with generator function.

Object.defineProperty(Object.prototype, Symbol.iterator, {
    value: function*() {
        let keys = Object.keys(this);
        for(let key of keys) {
            yield `${key}-${this[key]}`;
        }
    },
    enumerable: false
});

let obj = {a: "b", c: "d"};
for(let kv of obj) {
    console.log(kv); // a-b c-d
}
In practice

With the technique in hand, we can make custom datatypes iterable.

class Group {
    constructor() {
        this._data = [];
    }

    add(it) {
        this._data.push(it);
    }

    delete(it) {
        let index = this._data.indexOf(it);
        if(index >= 0) {
            this._data.splice(index, 1);
        }
    }

    has(it) {
        return this._data.includes(it);
    }

    [Symbol.iterator]() {
        let index = 0;
        return {
            next: () => ({
                value: this._data[index++],
                done: index > this._data.length
            })
        };
    }

    static from(iterable) {
        let group = new Group();
        for(let item of iterable) {
            group.add(item);
        }
        return group;
    }
}

let group = Group.from(["a", "b", "c"]);
console.log(group)

for (let value of group) {
    console.log(value);
}

console.log([...group]);
Reference

Eloquent JavaScript

Notice

If you want to follow the latest news/articles for the series of reading notes, Please 「Watch」to Subscribe.

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

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

相关文章

  • Javascript Generator - 函数式编程 - Javascript核心

    摘要:中的的引入,极大程度上改变了程序员对迭代器的看法,并为解决提供了新方法。被称为,也有些人把的返回值称为一个。其中属性包含实际返回的数值,属性为布尔值,标记迭代器是否完成迭代。 原文: http://pij.robinqu.me/JavaScript_Core/Functional_JavaScript/JavaScript_Generator.html 源代码: htt...

    yearsj 评论0 收藏0
  • ES6 变量声明与赋值:值传递、浅拷贝与深拷贝详解

    摘要:变量声明与赋值值传递浅拷贝与深拷贝详解归纳于笔者的现代开发语法基础与实践技巧系列文章。变量声明在中,基本的变量声明可以用方式允许省略,直接对未声明的变量赋值。按值传递中函数的形参是被调用时所传实参的副本。 ES6 变量声明与赋值:值传递、浅拷贝与深拷贝详解归纳于笔者的现代 JavaScript 开发:语法基础与实践技巧系列文章。本文首先介绍 ES6 中常用的三种变量声明方式,然后讨论了...

    snowLu 评论0 收藏0
  • JavaScript 实现链表

    摘要:相反,双向链表具有指向其前后元素的节点。另外,可以对链表进行排序。这个实用程序方法用于打印链表中的节点,仅用于调试目的。第行将更新为,这是从链表中弹出最后一个元素的行为。如果链表为空,则返回。 showImg(https://segmentfault.com/img/bVbsaI7?w=1600&h=228); 什么是链表 单链表是表示一系列节点的数据结构,其中每个节点指向链表中的下一...

    appetizerio 评论0 收藏0
  • Javascript数组的“字符串”索引 & for…in 和 for…of的区别

    摘要:中的数组是没有字符串索引的,形如只是在对象上添加了属性。本来有几个例子,然而搜到了的文档,所以摘一点下面摘自循环会遍历一个对象上面的所有属性。语法是针对集合的,而不是所有的对象。它会遍历定义了属性的集合的所有元素。 TL;DR:js中的数组是没有字符串索引的,形如array[b] = someValue只是在array对象上添加了属性。 本来有几个例子,然而搜到了MDN的文档,所以摘一...

    mo0n1andin 评论0 收藏0
  • [译]JavaScript ES6迭代器指南

    摘要:前言又称提供一个全新的迭代器的概念,它允许我们在语言层面上定义一个有限或无限的序列。后者可以被用来帮助我们理解迭代器。但是当我们使用迭代器时,这个问题就迎刃而解了。是中的新语法,用来配合迭代器。这是因为数组的迭代器只返回其中预期的元素。 前言 EcmaScript 2015 (又称ES6)提供一个全新的迭代器的概念,它允许我们在语言层面上定义一个(有限或无限的)序列。 暂时先抛开它...

    daryl 评论0 收藏0

发表评论

0条评论

kviccn

|高级讲师

TA的文章

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