美文网首页
小工具iterate学习(加快类数组的遍历速度)

小工具iterate学习(加快类数组的遍历速度)

作者: Gary嘉骏 | 来源:发表于2018-08-13 10:14 被阅读0次

github地址

  • 这是一个能在MapSet使用数组方法(如:map()filter(), reduce())。

  • 而且如果使用多个操作符时,能只迭代一次,而不是补个操作符迭代一次。大大加快运行速度,对于运行一个很大的Set会有明显的效果。

这个包应用了ES6的Iterator的概念。默认可遍历的数据结构是具有Symbol.iterator的属性。通过运行next方法就可以获得如下对象

{value:值, done: 是否到最后};

包用法:

iterate(uris)
  .filter(uri => uri.startsWith('file://'))
  .map(uri => uri.substr('file:///'.length))
  .toSet()

简单说,toSet()之前都是在不停装饰实例,成为一个新的遍历器。之后才开始迭代。

iterate(uris)

上面逻辑是:

function iterate<T>(collection: Iterator<T> | Iterable<T>): IteratorWithOperators<T> {
    return new IteratorWithOperators(toIterator(collection))
}

就是用被传入对象的遍历器生成一个新的可遍历对象。

export class IteratorWithOperators<T> implements IterableIterator<T> {
    /**
     * @param source Iterator to wrap
     */
    constructor(private source: Iterator<T>) {}

    /**
     * Returns a `{ value, done }` object that adheres to the Iterator protocol
     */
    next(): IteratorResult<T> {
        return this.source.next()
    }

    /**
     * The presence of this method makes the Iterator itself Iterable.
     * This makes it possible to pass it to `for of` and Iterable-accepting functions like `Array.from()`
     */
    [Symbol.iterator](): this {
        return this
    }

    /**
     * Returns a new Iterator by running each element thru iteratee
     */
    map<R>(iteratee: (value: T) => R): IteratorWithOperators<R> {
        return new IteratorWithOperators(new MapIterator(this.source, iteratee))
    }
....

能看出其实现了[Symbol.iterator]的方法,所以是可遍历的。

我们看下map操作的实现就明白为何会只迭代一次。直接看
new MapIterator(this.source, iteratee)

export class MapIterator<T, R> implements Iterator<R> {
    constructor(private source: Iterator<T>, private iteratee: (value: T) => R) {}

    next(): IteratorResult<R> {
        const { value, done } = this.source.next()
        return { value: !done && this.iteratee(value), done } as IteratorResult<R>
    }
}

可以看出,实例生成时,支撑保存了遍历器与处理方法。

所以当最后调用IteratorWithOperators的非操作符的遍历方法时,会自动去调用遍历器的next方法,从最底层开始,一层一层的往上调用操作符的逻辑,所以最底层遍历结束,整体也进入最后结束轮,仅需遍历一次。

PS: 也可以看出所有逻辑都是同步的。其实使用RxJS也是可以只遍历一次,如:

of([1,2,3,4]).pipe(tap(....),map(...),mergeMap(....)).subscribe(cb)

但这个包可以让我们类似用原生的方法去操作,比较亲切。

如果觉得文章对你有点用的话,麻烦拿出手机,这里有一个你我都有的小福利(每天一次): 打开支付宝首页搜索“8601304”,即可领红包。谢谢支持

相关文章

  • 小工具iterate学习(加快类数组的遍历速度)

    github地址 这是一个能在Map和Set使用数组方法(如:map()、filter(), reduce())。...

  • 快捷键

    一、遍历 遍历就近数组:增强:iter Iterate (for each..in)

  • 数组遍历速度&for循环速度

    遍历是日常操作,这篇文章比较详细 循环遍历总结for/foreach/forin/forof/map/some/f...

  • for... in与for...of

    for...in 循环主要是为了遍历对象而生,不适用于遍历数组for...of循环可以用来遍历数组、类数组对象,字...

  • Sass预编译语法

    1. 遍历@each,完成padding类、font-size计算类. @each in遍历、$变量、定义数组的圆...

  • 伪数组

    伪数组(类数组):无法直接调用数组方法或期望 length 属性有什么特殊的行为,但仍可以对真正数组遍历方法来遍历...

  • 在Javascript中什么是伪数组?如何将伪数组转化为标准数组

    伪数组(类数组):无法直接调用数组方法或期望length属性有什么特殊的行为,但仍可以对真正数组遍历方法来遍历它们...

  • [].slice.call(arguments)原理解析

    javascirpt的类数组对象可以像数组一样使用for循环遍历,但是却不能调用数组原型链的方法,为了让类数组对象...

  • 2021-04-16

    javascirpt的类数组对象可以像数组一样使用for循环遍历,但是却不能调用数组原型链的方法,为了让类数组对象...

  • oop_iterate

    GC引用遍历时最终都会碰到oopDesc::oop_iterate这个方法,用来遍历该对象所引用的其他对象,本篇博...

网友评论

      本文标题:小工具iterate学习(加快类数组的遍历速度)

      本文链接:https://www.haomeiwen.com/subject/vfdybftx.html