在PHP中,您可以。。。

range(1, 3); // Array(1, 2, 3)
range("A", "C"); // Array("A", "B", "C")

也就是说,有一个函数可以通过传递上下限来获得一系列数字或字符。

JavaScript本机是否有内置的功能?如果没有,我将如何实施?


当前回答

对于数字,您可以使用ES6 Array.from(),它现在可以在除IE以外的任何情况下工作:

较短版本:

Array.from({length: 20}, (x, i) => i);

更长版本:

Array.from(new Array(20), (x, i) => i);​​​​​​

这创建了从0到19(包括0到19)的数组。这可以进一步简化为以下形式之一:

Array.from(Array(20).keys());
// or
[...Array(20).keys()];

也可以指定下限和上限,例如:

Array.from(new Array(20), (x, i) => i + *lowerBound*);

一篇文章对此进行了更详细的描述:http://www.2ality.com/2014/05/es6-array-methods.html

其他回答

简单范围函数:

function range(start, stop, step) {
    var a = [start], b = start;
    while (b < stop) {
        a.push(b += step || 1);
    }
    return a;
}

要合并BigInt数据类型,可以包括一些检查,以确保所有变量都是相同的开始类型:

function range(start, stop, step) {
    var a = [start], b = start;
    if (typeof start == 'bigint') {
        stop = BigInt(stop)
        step = step? BigInt(step): 1n;
    } else
        step = step || 1;
    while (b < stop) {
        a.push(b += step);
    }
    return a;
}

要删除高于停止定义的值,例如范围(0,5,2)将包括6,但不应是。

function range(start, stop, step) {
    var a = [start], b = start;
    while (b < stop) {
        a.push(b += step || 1);
    }
    return (b > stop) ? a.slice(0,-1) : a;
}

解决方案:

//best performance
var range = function(start, stop, step) {
    var a = [start];
    while (start < stop) {
        start += step || 1;
        a.push(start);
    }
    return a;
};

//or
var range = function(start, end) {
    return Array(++end-start).join(0).split(0).map(function(n, i) {
        return i+start
    });
}

使用Harmony生成器,除IE11外,所有浏览器都支持:

var take = function (amount, generator) {
    var a = [];

    try {
        while (amount) {
            a.push(generator.next());
            amount -= 1;
        }
    } catch (e) {}

    return a;
};

var takeAll = function (gen) {
    var a = [],
        x;

    try {
        do {
            x = a.push(gen.next());
        } while (x);
    } catch (e) {}

    return a;
};

var range = (function (d) {
    var unlimited = (typeof d.to === "undefined");

    if (typeof d.from === "undefined") {
        d.from = 0;
    }

    if (typeof d.step === "undefined") {
        if (unlimited) {
            d.step = 1;
        }
    } else {
        if (typeof d.from !== "string") {
            if (d.from < d.to) {
                d.step = 1;
            } else {
                d.step = -1;
            }
        } else {
            if (d.from.charCodeAt(0) < d.to.charCodeAt(0)) {
                d.step = 1;
            } else {
                d.step = -1;
            }
        }
    }

    if (typeof d.from === "string") {
        for (let i = d.from.charCodeAt(0); (d.step > 0) ? (unlimited ? true : i <= d.to.charCodeAt(0)) : (i >= d.to.charCodeAt(0)); i += d.step) {
            yield String.fromCharCode(i);
        }
    } else {
        for (let i = d.from; (d.step > 0) ? (unlimited ? true : i <= d.to) : (i >= d.to); i += d.step) {
            yield i;
        }
    }
});

示例

take

示例1。

尽可能多地索取

take(10,范围({从:100,步骤:5,到:120}))

回报

[100, 105, 110, 115, 120]

示例2。

不需要

take(10,范围({从:100,步骤:5}))

回报

[100, 105, 110, 115, 120, 125, 130, 135, 140, 145]

全部接受

示例3。

来自不必要的

takeAll(范围({到:5}))

回报

[0, 1, 2, 3, 4, 5]

示例4。

takeAll(范围({到:500,步骤:100}))

回报

[0, 100, 200, 300, 400, 500]

示例5。

takeAll(范围({从:“z”到:“a”}))

回报

[“z”、“y”、“x”、“w”、“v”、“u”、“t”、“s”、“r”、“q”、“p”、“o”、“n”、“m”、“l”、“k”、“j”、“i”、“h”、“g”、“f”、“e”、“d”、“c”、“b”、“a”]

对一些不同的范围函数进行了研究。检查执行这些函数的不同方法的jsperf比较。当然不是一个完美或详尽的列表,但应该有帮助:)

获胜者是。。。

function range(lowEnd,highEnd){
    var arr = [],
    c = highEnd - lowEnd + 1;
    while ( c-- ) {
        arr[c] = highEnd--
    }
    return arr;
}
range(0,31);

从技术上讲,它不是firefox上最快的,但铬合金上的疯狂速度差(imho)弥补了这一点。

还有一个有趣的观察是,与firefox相比,chrome使用这些阵列功能的速度要快得多。Chrome速度至少快4或5倍。

您可以使用lodash或Undescore.js范围:

var range = require('lodash/range')
range(10)
// -> [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

或者,如果您只需要连续的整数范围,则可以执行以下操作:

Array.apply(undefined, { length: 10 }).map(Number.call, Number)
// -> [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

在ES6范围内,可使用发电机实现:

function* range(start=0, end=null, step=1) {
  if (end == null) {
    end = start;
    start = 0;
  }

  for (let i=start; i < end; i+=step) {
    yield i;
  }
}

这种实现在迭代大型序列时节省了内存,因为它不必将所有值具体化为数组:

for (let i of range(1, oneZillion)) {
  console.log(i);
}