Je sais qu'il est utilisé pour transformer les arguments en un véritable tableau, mais je ne comprends pas ce qui se passe lors de l'utilisation de Array.prototype.slice.call(arguments)
Ce qui se passe sous le capot est que lorsque .slice()
est appelée normalement, this
est un tableau, puis il itère simplement sur ce tableau et fait son travail.
Comment this
dans .slice()
fonctionne-t-il avec un tableau? Parce que quand tu fais:
object.method();
... la object
devient automatiquement la valeur de this
dans la method()
. Donc avec:
[1,2,3].slice()
... le [1,2,3]
Array est défini avec la valeur de this
dans .slice()
.
Mais que se passerait-il si vous pouviez remplacer la valeur this
par quelque chose d'autre? Tant que ce que vous substituez aura une propriété numérique .length
et un ensemble de propriétés qui sont des index numériques, cela devrait fonctionner. Ce type d'objet est souvent appelé objet de type tableau .
Les méthodes .call()
et .apply()
vous permettent de définir manuellement la valeur de this
dans une fonction. Donc, si nous définissons la valeur de this
dans .slice()
sur un objet semblable à un tableau , .slice()
sera juste suppose que cela fonctionne avec un tableau, et fera son travail.
Prenez cet objet simple à titre d'exemple.
var my_object = {
'0': 'zero',
'1': 'one',
'2': 'two',
'3': 'three',
'4': 'four',
length: 5
};
Ce n'est évidemment pas un tableau, mais si vous pouvez le définir comme la valeur this
de .slice()
, alors cela fonctionnera, car il ressemble assez à un tableau pour que .slice()
fonctionne correctement .
var sliced = Array.prototype.slice.call( my_object, 3 );
Exemple: http://jsfiddle.net/wSvkv/
Comme vous pouvez le voir dans la console, le résultat est ce que nous attendons:
['three','four'];
C'est donc ce qui se produit lorsque vous définissez un objet arguments
comme valeur this
de .slice()
. Étant donné que arguments
a une propriété .length
et de nombreux index numériques, .slice()
poursuit son travail comme s'il travaillait sur un véritable tableau.
L'objet 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 n'a pas la méthode slice.
Les tableaux ont cette méthode, et comme l'objet arguments
est très similaire à un tableau, les deux sont compatibles. Cela signifie que nous pouvons utiliser des méthodes de tableau avec l'objet arguments. Et puisque les méthodes de tableau ont été construites avec les tableaux à l'esprit, elles renverront des tableaux plutôt que d'autres objets d'argument.
Alors pourquoi utiliser Array.prototype
? La Array
est l'objet à partir duquel nous créons de nouveaux tableaux (new Array()
), et ces nouveaux tableaux sont des méthodes et des propriétés transmises, comme slice. Ces méthodes sont stockées dans l'objet [Class].prototype
. Ainsi, par souci d'efficacité, au lieu d'accéder à la méthode slice par (new Array()).slice.call()
ou [].slice.call()
, nous l'obtenons directement à partir du prototype. Cela évite d'initialiser un nouveau tableau.
Mais pourquoi devons-nous faire cela en premier lieu? Comme vous l'avez dit, il convertit un objet arguments en instance Array. La raison pour laquelle nous utilisons slice, cependant, est plus un "hack" qu'autre chose. La méthode slice prendra une tranche d'un tableau, vous l'aurez deviné, et retournera cette tranche sous la forme d'un nouveau tableau. En ne lui passant aucun argument (hormis l'objet arguments en tant que contexte), la méthode slice prend un bloc complet du "tableau" passé (dans ce cas, l'objet arguments) et le renvoie sous la forme d'un nouveau tableau.
Normalement, en appelant
var b = a.slice();
va copier le tableau a
dans b
. Cependant, nous ne pouvons pas faire
var a = arguments.slice();
parce que arguments
n'est pas un vrai tableau et n'a pas slice
comme méthode. Array.prototype.slice
est la fonction slice
pour les tableaux et call
exécute la fonction avec this
réglé sur arguments
.
// 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]
Tout d’abord, vous devriez lire comment l’appel de fonction fonctionne en JavaScript . Je suppose que cela suffit à répondre à votre question. Mais voici un résumé de ce qui se passe:
Array.prototype.slice
extrait le slice
méthode à partir de Array
's prototype . Mais l'appeler directement ne fonctionnera pas, comme c'est une méthode (pas une fonction) et nécessite donc un contexte (un objet appelant, this
), sinon il lancerait Uncaught TypeError: Array.prototype.slice called on null or undefined
.
La méthode call()
vous permet de spécifier le contexte d'une méthode, en rendant fondamentalement ces deux appels équivalents:
someObject.slice(1, 2);
slice.call(someObject, 1, 2);
Sauf que le premier nécessite que la méthode slice
existe dans la chaîne de prototypes de someObject
(comme pour Array
), tandis que le dernier permet au contexte (someObject
) d'être passé manuellement à la méthode.
En outre, ce dernier est court pour:
var slice = Array.prototype.slice;
slice.call(someObject, 1, 2);
Quel est le même que:
Array.prototype.slice.call(someObject, 1, 2);
Array.prototype.slice.call (arguments) est la méthode traditionnelle pour convertir un argument en tableau.
Dans ECMAScript 2015, vous pouvez utiliser Array.from ou l'opérateur de propagation:
let args = Array.from(arguments);
let args = [...arguments];
C'est parce que, comme notes MDN
L'objet arguments n'est pas un tableau. Il est similaire à un tableau, mais ne possède aucune propriété de tableau à l'exception de la longueur. Par exemple, il n'a pas la méthode pop. Cependant, il peut être converti en un tableau réel:
Ici, nous appelons slice
sur l’objet natif Array
et non sur son implémentation et c’est pourquoi l’extra .prototype
var args = Array.prototype.slice.call(arguments);
N'oubliez pas que l'un des fondements basiques de ce comportement est la transposition de caractères intégrée entièrement dans JS-engine.
Slice ne prend que des objets (grâce à la propriété arguments.length existante) et retourne un objet tableau après que toutes les opérations aient été effectuées.
Les mêmes logiques que vous pouvez tester si vous essayez de traiter String-method avec une valeur INT:
String.prototype.bold.call(11); // returns "<b>11</b>"
Et cela explique la déclaration ci-dessus.
Il utilise la méthode slice
dont disposent les tableaux et l'appelle avec son objet this
étant l'objet arguments
. Cela signifie qu’il l’appelle comme si vous aviez arguments.slice()
en supposant que arguments
avait une telle méthode.
La création d'une tranche sans aucun argument prendra simplement tous les éléments. Elle sera donc simplement copiée des éléments de arguments
dans un tableau.
Supposons que vous avez: function.apply(thisArg, argArray )
La méthode apply appelle une fonction en transmettant l'objet qui sera lié à celle-ci ainsi qu'un tableau facultatif d'arguments.
La méthode slice () sélectionne une partie d'un tableau et renvoie le nouveau tableau.
Ainsi, lorsque vous appelez Array.prototype.slice.apply(arguments, [0])
, la méthode de division en tableau est invoquée (bind) sur des arguments.
Peut-être un peu tard, mais la réponse à tout ce désordre est que call () est utilisé dans JS pour l'héritage. Si nous comparons ceci à Python ou à PHP, par exemple, call est utilisé respectivement comme super (). init () ou parent ::_construction().
Ceci est un exemple de son utilisation qui clarifie tout:
function Teacher(first, last, age, gender, interests, subject) {
Person.call(this, first, last, age, gender, interests);
this.subject = subject;
}
Référence: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance
lorsque .slice () est appelé normalement, il s’agit d’un tableau, puis il itère sur ce tableau et fait son travail.
//ARGUMENTS
function func(){
console.log(arguments);//[1, 2, 3, 4]
//var arrArguments = arguments.slice();//Uncaught TypeError: undefined is not a function
var arrArguments = [].slice.call(arguments);//cp array with explicity THIS
arrArguments.Push('new');
console.log(arrArguments)
}
func(1,2,3,4)//[1, 2, 3, 4, "new"]