529 votes

comment fonctionne Array.prototype.slice.call() ?

Je sais qu'il est utilisé pour faire des arguments un vrai tableau, mais je ne comprends pas ce qui se passe lorsque l'on utilise Array.prototype.slice.call(arguments)

927voto

user113716 Points 143363

Ce qui se passe sous le capot, c'est que lorsque .slice() est appelé normalement, this est un tableau, et ensuite il itère simplement sur ce tableau, et fait son travail.

Comment this dans le .slice() fonction un tableau ? Parce que lorsque vous le faites :

object.method();

...le object devient automatiquement la valeur de this dans le method() . Donc avec :

[1,2,3].slice()

...le [1,2,3] Le tableau est défini comme la valeur de this sur .slice() .


Mais si vous pouviez substituer quelque chose d'autre comme le this valeur ? Tant que ce que vous substituez a une valeur numérique .length et un tas de propriétés qui sont des indices numériques, cela devrait fonctionner. Ce type d'objet est souvent appelé un objet de type tableau .

Le site .call() y .apply() Les méthodes vous permettent manuellement définir la valeur de this dans une fonction. Ainsi, si nous définissons la valeur de this sur .slice() à un objet de type tableau , .slice() sera juste supposez il travaille avec un tableau, et fera son travail.

Prenons l'exemple de cet objet ordinaire.

var my_object = {
    '0': 'zero',
    '1': 'one',
    '2': 'two',
    '3': 'three',
    '4': 'four',
    length: 5
};

Il ne s'agit évidemment pas d'un tableau, mais si vous pouvez le définir comme l'élément this valeur de .slice() alors cela fonctionnera, parce qu'il ressemble suffisamment à un tableau pour que l'on puisse l'utiliser. .slice() pour fonctionner correctement.

var sliced = Array.prototype.slice.call( my_object, 3 );

Ejemplo: http://jsfiddle.net/wSvkv/

Comme vous pouvez le voir dans la console, le résultat est conforme à nos attentes :

['three','four'];

Voici donc ce qui se passe lorsque vous définissez un arguments comme l'objet this valeur de .slice() . Parce que arguments a un .length et un certain nombre d'indices numériques, .slice() fait son travail comme s'il s'agissait d'un vrai Array.

98voto

Benjammin' Points 1057

Le site arguments n'est pas réellement une instance d'un tableau, et ne possède aucune des méthodes de tableau. Donc, arguments.slice(...) ne fonctionnera pas car l'objet arguments ne possède pas la méthode slice.

Les tableaux disposent de cette méthode, et parce que l'élément arguments est très similaire à un tableau, les deux sont compatibles. Cela signifie que nous pouvons utiliser les méthodes de tableau avec l'objet arguments. Et comme les méthodes de tableau ont été conçues pour les tableaux, elles renverront des tableaux plutôt que d'autres objets arguments.

Alors pourquoi utiliser Array.prototype ? Le site Array est l'objet à partir duquel nous créons de nouveaux tableaux ( new Array() ), et ces nouveaux tableaux reçoivent des méthodes et des propriétés, comme slice. Ces méthodes sont stockées dans le fichier [Class].prototype objet. Ainsi, par souci d'efficacité, au lieu d'accéder à la méthode slice par (new Array()).slice.call() o [].slice.call() nous l'obtenons directement du prototype. Ainsi, nous n'avons pas besoin d'initialiser un nouveau tableau.

Mais pourquoi devons-nous faire cela en premier lieu ? Eh bien, comme vous l'avez dit, cela convertit un objet arguments en une instance Array. La raison pour laquelle nous utilisons slice, cependant, est plus un "hack" qu'autre chose. La méthode slice prend une tranche d'un tableau, vous l'avez deviné, et renvoie cette tranche sous la forme d'un nouveau tableau. Si vous ne lui passez aucun argument (en dehors de l'objet arguments comme contexte), la méthode slice prendra un morceau complet du "tableau" passé (dans ce cas, l'objet arguments) et le retournera comme un nouveau tableau.

51voto

Delan Azabani Points 33013

Normalement, l'appel

var b = a.slice();

copiera le tableau a sur b . Cependant, nous ne pouvons pas faire

var a = arguments.slice();

parce que arguments n'est pas un vrai tableau, et ne possède pas de slice comme méthode. Array.prototype.slice est le slice pour les tableaux, et call exécute la fonction avec this réglé sur arguments .

23voto

sam Points 1960
// We can apply `slice` from  `Array.prototype`:
Array.prototype.slice.call([]); //-> []

// Since `slice` is available on an array's prototype chain,
'slice' in []; //-> true
[].slice === Array.prototype.slice; //-> true

// … we can just invoke it directly:
[].slice(); //-> []

// `arguments` has no `slice` method
'slice' in arguments; //-> false

// … but we can apply it the same way:
Array.prototype.slice.call(arguments); //-> […]

// In fact, though `slice` belongs to `Array.prototype`,
// it can operate on any array-like object:
Array.prototype.slice.call({0: 1, length: 1}); //-> [1]

10voto

naveen Points 21236

C'est parce que, comme Notes du MDN

L'objet arguments n'est pas un tableau. Il est similaire à un tableau, mais il ne possède aucune propriété de tableau, à l'exception de la longueur. Par exemple, il ne possède pas par exemple, il ne possède pas la méthode pop. Cependant, il peut être converti en un véritable tableau :

Ici, nous appelons slice sur l'objet natif Array et non sur son mise en œuvre et c'est pourquoi le supplément .prototype

var args = Array.prototype.slice.call(arguments);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X