Wiem, że służy on do przekształcenia argumentów w prawdziwą tablicę, ale nie rozumiem, co się dzieje podczas używania Array.prototype.slice.call(arguments)
474
Wiem, że służy on do przekształcenia argumentów w prawdziwą tablicę, ale nie rozumiem, co się dzieje podczas używania Array.prototype.slice.call(arguments)
Odpowiedzi:
To, co dzieje się pod maską, polega na tym, że gdy
.slice()
jest wywoływane normalnie,this
jest tablicą, a następnie po prostu iteruje po tej tablicy i wykonuje swoją pracę.Jak
this
w tej.slice()
funkcji jest tablica? Ponieważ kiedy to zrobisz:...
object
automatycznie staje się wartościąthis
wmethod()
. Więc z:...
[1,2,3]
tablica jest ustawiona jako wartośćthis
in.slice()
.Ale co, jeśli możesz podstawić coś innego jako
this
wartość? Tak długo, jak cokolwiek, co podstawisz, ma.length
właściwość numeryczną i kilka właściwości, które są indeksami numerycznymi, powinno działać. Ten typ obiektu jest często nazywany obiektem tablicowym ..call()
I.apply()
metody pozwala ręcznie ustawić wartośćthis
w funkcji. Więc jeśli ustawimy wartośćthis
in.slice()
na obiekt podobny do tablicy ,.slice()
po prostu założymy, że działa on z tablicą i zrobi swoje.Weź ten prosty obiekt jako przykład.
Oczywiście nie jest to tablica, ale jeśli możesz ustawić ją jako
this
wartość.slice()
, to po prostu będzie działać, ponieważ wygląda wystarczająco podobnie do tablicy,.slice()
aby działała poprawnie.Przykład: http://jsfiddle.net/wSvkv/
Jak widać w konsoli, wynik jest taki, jakiego oczekujemy:
Tak dzieje się, gdy ustawisz
arguments
obiekt jakothis
wartość.slice()
. Ponieważarguments
ma.length
właściwość i kilka indeksów liczbowych,.slice()
po prostu działa tak, jakby działał na prawdziwej macierzy.źródło
Array.prototype.slice
opisu metody.for-in
stwierdzenie nie gwarantuje porządku. Algorytm używany przez.slice()
definiuje porządek numeryczny rozpoczynający się0
i kończący (nie włącznie) z.length
danym obiektem (lub tablicą lub czymkolwiek). Dzięki temu kolejność jest gwarantowana we wszystkich implementacjach.var obj = {2:"two", 0:"zero", 1: "one"}
. Jeśli użyjemyfor-in
do wyliczenia obiektu, nie ma gwarancji porządku. Ale jeśli używamyfor
, możemy ręcznie wymusić kolejność:for (var i = 0; i < 3; i++) { console.log(obj[i]); }
. Teraz wiemy, że właściwości obiektu zostaną osiągnięte w rosnącej kolejności numerycznej, którą zdefiniowaliśmy w naszejfor
pętli. Właśnie to.slice()
robi. Nie ma znaczenia, czy ma on rzeczywistą macierz. Rozpoczyna się od0
i uzyskuje dostęp do właściwości w rosnącej pętli.arguments
Obiekt nie jest faktycznie instancja Array, a nie ma żadnej z metod Array. Więcarguments.slice(...)
nie będzie działać, ponieważ obiekt argumentów nie ma metody plastra.Tablice mają tę metodę, a ponieważ
arguments
obiekt jest bardzo podobny do tablicy, dwie są kompatybilne. Oznacza to, że możemy korzystać z metod tablicowych z argumentami sprzeciwu. A ponieważ metody tablicowe zostały zbudowane z myślą o tablicach, zwracają tablice zamiast innych obiektów argumentów.Dlaczego więc korzystać
Array.prototype
? JestArray
to obiekt, z którego tworzymy nowe tablice z (new Array()
), a te nowe tablice są przekazywane metodami i właściwościami, takimi jak plasterek. Te metody są przechowywane w[Class].prototype
obiekcie. Tak więc, ze względu na wydajność, zamiast uzyskiwać dostęp do metody wycinania za pomocą(new Array()).slice.call()
lub[].slice.call()
, po prostu pobieramy ją prosto z prototypu. Dzieje się tak, dlatego nie musimy inicjować nowej tablicy.Ale dlaczego musimy to zrobić w pierwszej kolejności? Cóż, jak powiedziałeś, przekształca obiekt argumentów w instancję Array. Powodem, dla którego używamy wycinka, jest bardziej „hack” niż cokolwiek innego. Metoda wycinania weźmie, jak zgadłeś, wycinek tablicy i zwróci ten wycinek jako nową tablicę. Nie przekazanie do niego żadnych argumentów (oprócz obiektu argumentów jako kontekstu) powoduje, że metoda slice pobiera pełny fragment przekazanej „tablicy” (w tym przypadku obiekt argumentów) i zwraca ją jako nową tablicę.
źródło
Zwykle dzwonienie
skopiuje tablicę
a
dob
. Jednak nie możemy tego zrobićponieważ
arguments
nie jest prawdziwą tablicą i nie maslice
jako metody.Array.prototype.slice
jestslice
funkcją dla tablic icall
uruchamia funkcję zthis
ustawioną naarguments
.źródło
prototype
? nieslice
jest rodzimąArray
metodą?Array
jest to funkcja konstruktora, a odpowiednia „klasa” toArray.prototype
. Możesz także użyć[].slice
slice
to metoda każdejArray
instancji, ale nieArray
funkcja konstruktora. Służyszprototype
do uzyskiwania dostępu do metod teoretycznych wystąpień konstruktora.Najpierw powinieneś przeczytać, jak działa wywoływanie funkcji w JavaScript . Podejrzewam, że sam wystarczy, aby odpowiedzieć na twoje pytanie. Ale oto podsumowanie tego, co się dzieje:
Array.prototype.slice
wyodrębnia sposób z „S prototypu . Ale bezpośrednie wywołanie nie zadziała, ponieważ jest to metoda (a nie funkcja) i dlatego wymaga kontekstu (obiektu wywołującego ), w przeciwnym razie zostałby rzucony .slice
Array
this
Uncaught TypeError: Array.prototype.slice called on null or undefined
call()
Metoda pozwala określić kontekst sposobu, w zasadzie czyni te dwa połączenia równoważne:Poza tym pierwszym wymaga, aby
slice
metoda istniała wsomeObject
łańcuchu prototypów (tak jak ma to miejsce w przypadkuArray
), podczas gdy ten drugi umożliwiasomeObject
ręczne przekazanie kontekstu ( ) do metody.To drugie jest również skrótem od:
Który jest taki sam jak:
źródło
źródło
Array.prototype.slice.call (arguments) to staromodny sposób konwersji argumentów na tablicę.
W ECMAScript 2015 możesz użyć Array.from lub operatora rozprzestrzeniania:
źródło
Jest tak, ponieważ, jak zauważa MDN
Wzywamy tutaj
slice
natywny obiekt,Array
a nie jego implementację, i dlatego dodatkowe.prototype
źródło
Nie zapominaj, że niskim poziomem podstaw tego zachowania jest rzutowanie typu, które całkowicie zintegrowało się z silnikiem JS.
Slice po prostu pobiera obiekt (dzięki istniejącej właściwości arguments.length) i zwraca rzutowany obiekt tablicowy po wykonaniu wszystkich operacji na tym.
Te same logiki, które możesz przetestować, jeśli spróbujesz traktować metodę String za pomocą wartości INT:
I to wyjaśnia powyższe stwierdzenie.
źródło
Wykorzystuje
slice
tablice metod i wywołuje je,this
będącarguments
obiektem. Oznacza to, że nazywa go jako jeśli niearguments.slice()
zakładającarguments
miał taką metodę.Utworzenie wycinka bez żadnych argumentów po prostu zabierze wszystkie elementy - więc po prostu skopiuje je z
arguments
tablicy do tablicy.źródło
Załóżmy, że masz:
function.apply(thisArg, argArray )
Metoda slice () wybiera część tablicy i zwraca nową tablicę.
Więc kiedy wywołujesz
Array.prototype.slice.apply(arguments, [0])
tablicę, wywoływana jest metoda argumentu (bind).źródło
Może trochę późno, ale odpowiedzią na cały ten bałagan jest to, że call () jest używane w JS do dziedziczenia. Jeśli porównamy to na przykład do Pythona lub PHP, wywołanie zostanie użyte odpowiednio jako super (). init () lub parent :: _ construct ().
To jest przykład użycia, który wyjaśnia wszystkie:
Odniesienie: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance
źródło
gdy .slice () jest wywoływane normalnie, jest to Array, a następnie po prostu iteruje tę tablicę i wykonuje swoją pracę.
źródło
Piszę to, żeby sobie przypomnieć ...
Lub po prostu użyj tej przydatnej funkcji $ A, aby zamienić większość rzeczy w tablicę.
przykładowe użycie ...
źródło