Ви можете зробити це:
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,55775759159558545, 0,1577575915958765, 0,1577575915958735, 0,157, 755, 15955, 585, 0,16, 755, 15955, 585, 0,16, 6005, 15955, 585, 0,16, 755, 1595, 585, 0,16, 6005, 1595, 585, 0,16, 755, 555, 585, 575, 596, 585, 585, 585, 585, 585, 585, 575, 585]
Пояснення
По-перше, зауважте, що 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.