Ich weiß, dass es verwendet wird, um arguments
eine echte Array
aber ich verstehe nicht, was passiert, wenn ich Array.prototype.slice.call(arguments);
.
Antworten
Zu viele Anzeigen?Was unter der Haube passiert ist, dass wenn .slice()
normal aufgerufen wird, this
ist ein Array, und dann iteriert es einfach über dieses Array und erledigt seine Arbeit.
Wie ist this
im .slice()
Funktion ein Array? Denn wenn Sie das tun:
object.method();
...die object
wird automatisch der Wert von this
im method()
. Also mit:
[1,2,3].slice()
...die [1,2,3]
Array wird als der Wert von this
en .slice()
.
Aber was wäre, wenn Sie etwas anderes als die this
Wert? Solange das, was Sie ersetzen, einen numerischen Wert hat .length
Eigenschaft und eine Reihe von Eigenschaften, die numerische Indizes sind, sollte es funktionieren. Diese Art von Objekt wird oft als array-ähnliches Objekt .
El .call()
y .apply()
Methoden können Sie manuell setzen den Wert von this
in einer Funktion. Wenn wir also den Wert von this
en .slice()
zu einer array-ähnliches Objekt , .slice()
wird nur annehmen es arbeitet mit einem Array, und wird sein Ding machen.
Nehmen Sie dieses einfache Objekt als Beispiel.
var my_object = {
'0': 'zero',
'1': 'one',
'2': 'two',
'3': 'three',
'4': 'four',
length: 5
};
Dies ist offensichtlich kein Array, aber wenn Sie es als die this
Wert von .slice()
dann wird es einfach funktionieren, weil es wie ein Array aussieht und .slice()
richtig zu funktionieren.
var sliced = Array.prototype.slice.call( my_object, 3 );
Beispiel: http://jsfiddle.net/wSvkv/
Wie Sie in der Konsole sehen können, ist das Ergebnis das, was wir erwarten:
['three','four'];
Das passiert also, wenn Sie eine arguments
Objekt als this
Wert von .slice()
. Denn arguments
hat eine .length
Eigenschaft und eine Reihe von numerischen Indizes, .slice()
geht einfach seiner Arbeit nach, als ob es an einem echten Array arbeiten würde.
El arguments
Objekt ist nicht wirklich eine Instanz eines Arrays und verfügt über keine der Array-Methoden. Also, arguments.slice(...)
funktioniert nicht, da das Argumente-Objekt nicht über die Slice-Methode verfügt.
Arrays haben diese Methode, und weil die arguments
Objekt ist einem Array sehr ähnlich, die beiden sind kompatibel. Das bedeutet, dass wir Array-Methoden mit dem Argument Objekt verwenden können. Und da Array-Methoden mit Blick auf Arrays entwickelt wurden, geben sie eher Arrays als andere Argumentobjekte zurück.
Warum also die Array.prototype
? Die Array
ist das Objekt, aus dem wir neue Arrays erstellen ( new Array()
), und diesen neuen Arrays werden Methoden und Eigenschaften wie slice übergeben. Diese Methoden werden in der [Class].prototype
Objekt. Aus Gründen der Effizienz sollte der Zugriff auf die Slice-Methode also nicht über (new Array()).slice.call()
o [].slice.call()
Wir holen es uns einfach direkt vom Prototyp. Dies ist so, dass wir nicht ein neues Array initialisieren müssen.
Aber warum müssen wir das überhaupt tun? Nun, wie Sie schon sagten, wird damit ein Argument-Objekt in eine Array-Instanz umgewandelt. Der Grund, warum wir slice verwenden, ist jedoch mehr ein "Hack" als alles andere. Die slice-Methode nimmt einen, Sie ahnen es, Ausschnitt eines Arrays und gibt diesen Ausschnitt als neues Array zurück. Wenn man ihr keine Argumente übergibt (außer dem arguments-Objekt als Kontext), nimmt die slice-Methode einen kompletten Teil des übergebenen "Arrays" (in diesem Fall das arguments-Objekt) und gibt ihn als neues Array zurück.
Normalerweise wird der Aufruf
var b = a.slice();
kopiert das Array a
in b
. Allerdings können wir nicht tun
var a = arguments.slice();
denn arguments
hat keine slice
als Methode (es handelt sich nicht um ein echtes Array).
Array.prototype.slice
es el slice
Funktion für Arrays. .call
läuft dies slice
Funktion, mit der this
Wert eingestellt auf arguments
.
Zuerst sollten Sie lesen wie Funktionsaufrufe in JavaScript funktionieren . Ich vermute, das allein reicht aus, um Ihre Frage zu beantworten. Aber hier ist eine Zusammenfassung dessen, was passiert:
Array.prototype.slice
extrahiert die slice
Methode von Array
's Prototyp . Aber direkt anrufen wird nicht funktionieren, da es sich um eine Methode (nicht um eine Funktion) handelt und erfordert daher einen Kontext (ein aufrufendes Objekt), this
), sonst würde es Uncaught TypeError: Array.prototype.slice called on null or undefined
.
El call()
Methode können Sie den Kontext einer Methode angeben, was diese beiden Aufrufe im Grunde gleichwertig macht:
someObject.slice(1, 2);
slice.call(someObject, 1, 2);
Außer bei ersterem muss die slice
Methode zu existieren someObject
Prototypenkette (wie bei Array
), während letztere den Kontext ( someObject
), die manuell an die Methode übergeben werden müssen.
Letzteres ist auch eine Abkürzung für:
var slice = Array.prototype.slice;
slice.call(someObject, 1, 2);
Das ist dasselbe wie:
Array.prototype.slice.call(someObject, 1, 2);
- See previous answers
- Weitere Antworten anzeigen