NodeJS总结(三):一种快速生成序列的方法

来源:互联网 发布:醉游网络 编辑:程序博客网 时间:2024/06/10 13:09

习惯了python、R等编程语言自带序列的写法,突然想把这样的行为移植到JS中,在NodeJS中,如果要快速生成一个[0-9]的数组,那么最快捷的写法是:

//  生成[0,1,2,3,4,5,6,7,8,9][...Array[10].keys()]

对于上面的写法,理解分为[]步:
1. Array[10]返回一个10个undefined元素的数组;
2. keys()返回数组元素的迭代器,用于对键名的遍历,对数组而言,也就是索引;
3. …代表扩展运算符,用于将数组转换为参数序列(请理解为apply函数),即0,1,2,3,4,5,6,7,8,9;
4. []代表调用Array()方法,最后当然返回一个10个元素的数组;

所以,上述的写法可改写为:

let array = Array(10),    indexs = array.keys(),    result = Array(...indexs)//  输出结果console.log(result)

那么我们要取10到20的序列,那么就可以采用类似的方法,如下:

[...Array(21).keys()].slice(11)

显然这样的写法实在太低效了,也太浪费存储空间了,并且无法定制步进,从而灵活性也不强,既然这样,那我们能不能利用类似扩展运算符的语法,用下面的写法定义自己的序列呢?

//  2代表起始数字,20代表结束数字,3代码步进[...range(2, 20, 3)]

这里我们可以充分使用ES 6的iterator特性,定义如下的Range构造函数:

class Range {    constructor(start, end, step) {        this.start = start        this.end = end        this.step = step    }    /**     *  定义迭代器函数,是实现迭代器效果的关键     */    [Symbol.iterator] () {        let curr = this.start,            _this = this        return {            next () {                let result = curr < _this.end ? {                    value : curr,                    done : false                 } : {                    value : undefined,                    done : true                }                curr = curr + _this.step                return result            }        }    }}

Symbol.iterator是扩展对象支持迭代模式枚举常量,必须以上述的方式进行引用,以保持对Symbol类型的唯一性。

上面的写法虽然实现了功能,但稍嫌啰嗦,我们可以用yield对其进行改进,如下:

[Symbol.iterator] () {    let curr = this.start,        _this = this    //  必须要添加*号    return function* () {        //  必须要使用循环        while(curr < _this.end) {            yield curr            curr = curr + _this.step        }    }() //  必须要对此函数进行执行}

最后,我们只需要对其进行简单的包装即可完成所有的任务:

function range(start, end, step) {    return new Range(start, end, step)}

现在我们就可以利用自定义序列了,如下:

//  输出[ 5, 10, 15, 20 ][...range(5, 25, 5)]//  输出[ 100, 110, 120, 130, 140, 150, 160, 170, 180, 190 ][...range(100, 200, 10)]

结论

利用内置的Symbol.iterator与yield,我们可以轻易构造出自定义的序列数组。

原创粉丝点击