2008-09-23 18 views
27

Ich gehe durch John Resig ausgezeichnete Advanced javascript tutorial und ich verstehe nicht gründlich, was ist der Unterschied zwischen den folgenden Aufrufe: (Bitte beachten Sie, dass 'Argumente' ist ein eingebautes Javascript Wort und ist nicht gerade ein Array daher mit dem Array.slice des Hacking, anstatt einfach Aufruf arguments.slice)Unterschied zwischen Array.slice und Array(). Slice

>>> arguments 
[3, 1, 2, 3] 
>>> Array.slice.call(arguments) 
3,1,2,3 0=3 1=1 2=2 3=3 
>>> Array.slice.call(arguments, 1) 
[] 
>>> Array().slice.call(arguments) 
3,1,2,3 0=3 1=1 2=2 3=3 
>>> Array().slice.call(arguments, 1) 
1,2,3 0=1 1=2 2=3 

im Grunde kocht mein Missverständnis zwischen Array.slice der Differenz nach unten und Array(). Slice. Was genau ist der Unterschied zwischen diesen beiden und warum verhält sich Array.slice.call nicht wie erwartet? (was alles außer dem ersten Element der Argumentenliste zurückgibt).

Antwort

38

Nicht ganz.

beobachten, was passiert, wenn Sie String.substring.call ("foo", 1) und String() substring.call ("foo", 2) nennen.

>>> String.substring.call("foo", 1) 
"1" 

>>> String().substring.call("foo", 1) 
"oo" 

Array.slice ist weder, die die Slice-Funktion korrekt referenziert, die dem Array-Prototyp beigefügt ist, noch die Slice-Funktion, die an eine instanziierte Array-Instanz angehängt ist (z. B. Array() oder []).

Die Tatsache, dass Array.slice überhaupt nicht null ist, ist eine falsche Implementierung des Objekts (/ function/constructor). Versuchen Sie, den entsprechenden Code in IE auszuführen, und Sie erhalten eine Fehlermeldung, dass Array.slice null ist.

Aus diesem Grund verhält sich Array.slice nicht richtig (noch StringString).

Beweis (das folgende ist etwas, das man sollte nie auf die Definition von slice() ... wie substring() oben auf Basis erwarten):

>>> Array.slice.call([1,2], [3,4]) 
3,4 

Nun, wenn Sie richtig slice() aufrufen, auf entweder eine instanzierte Objekt oder der Array-Prototyp, werden Sie bekommen, was Sie erwarten:

>>> Array.prototype.slice.call([4,5], 1) 
[5] 
>>> Array().slice.call([4,5], 1) 
[5] 

Mehr Beweis ...

>>> Array.prototype.slice == Array().slice 
true 
>>> Array.slice == Array().slice 
false 
+0

Ich weiß nicht, wie es sich in '08 Browsern verhalten hat, aber seit Anfang 2013 wirft 'String.substring.call' einen TypeError in Chrome (da der' String' Konstruktor keine 'substring' Eigenschaft hat) . – bfavaretto

+0

@bfavaretto, Firefox (allein) implementiert 'Array.slice' und' String.substring'. Der Fragesteller benutzte zweifellos Firefox, als er das ausprobierte. –

+0

Danke für die Info, @NathanWall. Das ist ziemlich seltsam von Firefox, wahrscheinlich etwas, das sie als eine Abkürzung zu "String.prototypeString" et al. aus Gründen der Abwärtskompatibilität ... und es scheint, dass es für eine Weile anhielt. – bfavaretto

6

Array ist nur eine Funktion, wenn auch eine spezielle (zur Initialisierung von Arrays). Array.slice ist eine Referenz auf die Funktion slice() im Array-Prototyp. Es kann nur für ein Array-Objekt und nicht für den Konstruktor (d. H. Array) selbst aufgerufen werden. Array scheint sich jedoch speziell zu verhalten, da Array() ein leeres Array zurückgibt. Dies scheint nicht für nicht eingebaute Konstruktorfunktionen zu funktionieren (dort muss man neu verwenden). So

Array().slice.call 

ist die gleiche wie

[].slice.call 
-1

Meine Vermutung ist, dass Array ein Prototyp ist, während Array() ein Array-Objekt ist. Abhängig von der JavaScript-Interpretation könnte der direkte Aufruf der Prototypmethode eines integrierten Objekttyps funktionieren oder nicht. Ich glaube nicht, dass die Spezifikation sagt, dass es funktionieren muss, nur dass das Aufrufen eines instanziierten Objekts funktioniert.

0

Ich glaube Array ist der Typ und Array() ist die Konstruktorfunktion.

Herumspielen in FireBug:

>>> Array === Array() 
false 

>>> Array.constructor 
Function() 

>>> Array().constructor 
Array() 
1

Wie funktioniert ein Aufruf von slice.call() in den bereitgestellten Beispielen, da kein Kontextparameter angegeben wird? Implementiert Slice seine eigene Aufrufmethode und übersteuert somit die Aufrufmethode von JavaScript? Die Methoden call und apply nehmen als ersten Parameter ein Objekt zur Angabe des Kontextobjekts (this) für den Aufruf an.

Verwandte Themen