Вы можете сделать это:
var N = 10;
Array.apply(null, {length: N}).map(Number.call, Number)
результат: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
или со случайными значениями:
Array.apply(null, {length: N}).map(Function.call, Math.random)
результат: [0,7082694901619107, 0,9572225909214467, 0,8586748542729765, 0,8653848143294454, 0,008339877473190427, 0,9911756622605026, 0,8133423360995948, 0,8377588465809822, 0,5577575915358745, 0,5577581530874532, 0,17617830308732
объяснение
Во-первых, обратите внимание, что Number.call(undefined, N)
это эквивалентно Number(N)
, который просто возвращает N
. Мы будем использовать этот факт позже.
Array.apply(null, [undefined, undefined, undefined])
эквивалентно Array(undefined, undefined, undefined)
, который создает массив из трех элементов и присваивает undefined
каждому элементу.
Как вы можете обобщить это на N элементов? Посмотрим, как Array()
работает, что-то вроде этого:
function Array() {
if ( arguments.length == 1 &&
'number' === typeof arguments[0] &&
arguments[0] >= 0 && arguments &&
arguments[0] < 1 << 32 ) {
return [ … ]; // array of length arguments[0], generated by native code
}
var a = [];
for (var i = 0; i < arguments.length; i++) {
a.push(arguments[i]);
}
return a;
}
Начиная с ECMAScript 5 , Function.prototype.apply(thisArg, argsArray)
также принимает массивоподобный объект типа утки в качестве второго параметра. Если мы вызовем Array.apply(null, { length: N })
, то он выполнит
function Array() {
var a = [];
for (var i = 0; i < /* arguments.length = */ N; i++) {
a.push(/* arguments[i] = */ undefined);
}
return a;
}
Теперь у нас есть N -элементный массив с каждым элементом, установленным в undefined
. Когда мы вызываем .map(callback, thisArg)
его, каждый элемент будет установлен в результат callback.call(thisArg, element, index, array)
. Следовательно, [undefined, undefined, …, undefined].map(Number.call, Number)
будет сопоставлять каждый элемент (Number.call).call(Number, undefined, index, array)
, что совпадает с Number.call(undefined, index, array)
, который, как мы наблюдали ранее, оценивает index
. Это завершает массив, элементы которого совпадают с их индексом.
Зачем переживать неприятности, Array.apply(null, {length: N})
а не просто Array(N)
? В конце концов, оба выражения приведут к массиву из N элементов с неопределенными элементами. Разница заключается в том, что в первом выражении каждый элемент явно установлен на неопределенное значение, тогда как в последнем каждый элемент никогда не задавался. Согласно документации .map()
:
callback
вызывается только для индексов массива, которым присвоены значения; он не вызывается для индексов, которые были удалены или которым никогда не присваивались значения.
Следовательно, Array(N)
недостаточно; Array(N).map(Number.call, Number)
приведет неинициализированный массив длиной N .
Совместимость
Поскольку этот метод основан на поведении, Function.prototype.apply()
указанном в ECMAScript 5, он не будет работать в браузерах до ECMAScript 5, таких как Chrome 14 и Internet Explorer 9.