Vous pouvez le faire:
var N = 10;
Array.apply(null, {length: N}).map(Number.call, Number)
résultat: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
ou avec des valeurs aléatoires:
Array.apply(null, {length: N}).map(Function.call, Math.random)
résultat: [0.7082694901619107, 0.9572225909214467, 0.8586748542729765, 0.8653848143294454, 0.008339877473190427, 0.9911756622605026, 0.8133423360995948, 0.8377588465809822, 0.5577575915958745, 0.16
Explication
Tout d'abord, notez que Number.call(undefined, N)
c'est équivalent à Number(N)
, qui revient juste N
. Nous utiliserons ce fait plus tard.
Array.apply(null, [undefined, undefined, undefined])
est équivalent à Array(undefined, undefined, undefined)
, ce qui produit un tableau à trois éléments et attribue undefined
à chaque élément.
Comment pouvez-vous généraliser cela à N éléments? Considérez comment cela Array()
fonctionne, ce qui ressemble à ceci:
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;
}
Depuis ECMAScript 5 , Function.prototype.apply(thisArg, argsArray)
accepte également un objet de type tableau de type canard comme deuxième paramètre. Si nous invoquons Array.apply(null, { length: N })
, il s'exécutera
function Array() {
var a = [];
for (var i = 0; i < /* arguments.length = */ N; i++) {
a.push(/* arguments[i] = */ undefined);
}
return a;
}
Nous avons maintenant un tableau à N éléments, chaque élément étant défini sur undefined
. Lorsque nous l'appellerons .map(callback, thisArg)
, chaque élément sera mis au résultat de callback.call(thisArg, element, index, array)
. Par conséquent, [undefined, undefined, …, undefined].map(Number.call, Number)
mapperait chaque élément à (Number.call).call(Number, undefined, index, array)
, ce qui est le même que Number.call(undefined, index, array)
, qui, comme nous l'avons observé précédemment, est évalué àindex
. Cela complète le tableau dont les éléments sont les mêmes que leur index.
Pourquoi passer par la peine de Array.apply(null, {length: N})
au lieu de juste Array(N)
? Après tout, les deux expressions résulteraient en un tableau d'éléments N non définis. La différence est que dans la première expression, chaque élément est explicitement défini sur indéfini, tandis que dans la seconde, chaque élément n'a jamais été défini. Selon la documentation de .map()
:
callback
est invoqué uniquement pour les index du tableau auxquels des valeurs ont été attribuées; il n'est pas appelé pour les index qui ont été supprimés ou auxquels aucune valeur n'a été affectée.
Par conséquent, Array(N)
est insuffisant; Array(N).map(Number.call, Number)
entraînerait un tableau non initialisé de longueur N .
Compatibilité
Étant donné que cette technique repose sur le comportement Function.prototype.apply()
spécifié dans ECMAScript 5, elle ne fonctionnera pas dans les navigateurs pré-ECMAScript 5 tels que Chrome 14 et Internet Explorer 9.