Uruchomiłem ten kod i otrzymałem poniższy wynik. Ciekawi mnie, dlaczego []
jest szybszy?
console.time('using[]')
for(var i=0; i<200000; i++){var arr = []};
console.timeEnd('using[]')
console.time('using new')
for(var i=0; i<200000; i++){var arr = new Array};
console.timeEnd('using new')
- za pomocą
[]
: 299 ms - za pomocą
new
: 363 ms
Dzięki Raynos jest to benchmark tego kodu i bardziej możliwy sposób definiowania zmiennej.
javascript
performance
Mohsen
źródło
źródło
[]
jest równoważnynew Array()
pod względem kodu źródłowego, a nie obiektów zwróconych z wyrażeńOdpowiedzi:
Dalsze rozszerzenie poprzednich odpowiedzi ...
Z ogólnej perspektywy kompilatorów i pomijając optymalizacje specyficzne dla maszyn wirtualnych:
Najpierw przechodzimy przez fazę analizy leksykalnej, w której tokenizujemy kod.
Przykładowo można wyprodukować następujące tokeny:
Miejmy nadzieję, że powinno to zapewnić wystarczającą wizualizację, abyś mógł zrozumieć, o ile więcej (lub mniej) jest wymagane przetwarzanie.
Na podstawie powyższych tokenów wiemy, że jako fakt ARRAY_INIT zawsze tworzy tablicę. Dlatego po prostu tworzymy tablicę i wypełniamy ją. Jeśli chodzi o niejednoznaczność, na etapie analizy leksykalnej już odróżniono ARRAY_INIT od metody dostępu do właściwości obiektu (np.
obj[foo]
) Lub nawiasów wewnątrz łańcuchów / literałów wyrażenia regularnego (np. „Foo [] bar” lub / [] /)To jest malutkie, ale mamy też więcej żetonów z
new Array
. Co więcej, nie jest jeszcze do końca jasne, że chcemy po prostu utworzyć tablicę. Widzimy „nowy” token, ale „nowy” co? Następnie widzimy token IDENTIFIER, który oznacza, że chcemy nowej „tablicy”, ale maszyny wirtualne JavaScript generalnie nie rozróżniają tokenu IDENTIFIER i tokenów dla „natywnych obiektów globalnych”. W związku z tym...Za każdym razem, gdy napotkamy token IDENTIFIER, musimy sprawdzić łańcuch zasięgu. Maszyny wirtualne JavaScript zawierają „obiekt aktywacji” dla każdego kontekstu wykonania, który może zawierać obiekt „argumenty”, lokalnie zdefiniowane zmienne itp. Jeśli nie możemy go znaleźć w obiekcie Activation, zaczynamy przeszukiwać łańcuch zasięgu, aż osiągniemy zasięg globalny . Jeśli nic nie zostanie znalezione, rzucamy
ReferenceError
.Po zlokalizowaniu deklaracji zmiennej wywołujemy konstruktor.
new Array
jest niejawnym wywołaniem funkcji, a ogólną zasadą jest to, że wywołania funkcji są wolniejsze podczas wykonywania (stąd dlaczego statyczne kompilatory C / C ++ pozwalają na „wstawianie funkcji” - które silniki JS JIT, takie jak SpiderMonkey, muszą wykonywać w locie)Array
Konstruktor jest przeciążony. Konstruktor Array jest zaimplementowany jako kod natywny, więc zapewnia pewne ulepszenia wydajności, ale nadal musi sprawdzać długość argumentów i odpowiednio działać. Ponadto, w przypadku podania tylko jednego argumentu, musimy dodatkowo sprawdzić typ argumentu. new Array ("foo") produkuje ["foo"], gdzie jako new Array (1) daje [undefined]A więc, upraszczając wszystko: dzięki literałom tablicowym maszyna wirtualna wie, że potrzebujemy tablicy; z
new Array
, VM musi użyć dodatkowych cykli procesora, aby dowiedzieć się, conew Array
właściwie robi.źródło
Jednym z możliwych powodów jest to, że
new Array
wymaga on wyszukiwania nazwyArray
(możesz mieć zmienną o tej nazwie w zakresie), a[]
nie.źródło
Array
z wyjątkiem jednego argumentulen
i wielu argumentów. Gdzie jako[]
akceptuje tylko wiele argumentów. Również testy Firefoksa nie wykazują prawie żadnej różnicy.var Array = window.Array
poprawia wydajnośćnew Array
testu.Dobre pytanie. Pierwszy przykład nazywa się literałem tablicowym. Jest to preferowany sposób tworzenia tablic wśród wielu programistów. Może się zdarzyć, że różnica w wydajności jest spowodowana sprawdzeniem argumentów nowego wywołania Array (), a następnie utworzeniem obiektu, podczas gdy literał tworzy bezpośrednio tablicę.
Myślę, że stosunkowo niewielka różnica w wydajności potwierdza ten punkt. Nawiasem mówiąc, możesz wykonać ten sam test z obiektem i literałem obiektu {}.
źródło
To miałoby jakiś sens
http://www.dyn-web.com/tutorials/obj_lit.php
źródło
Co ciekawe, jeśli długość tablicy jest znana z góry (elementy zostaną dodane zaraz po utworzeniu), użycie konstruktora tablicy o określonej długości jest znacznie szybsze w najnowszym Google Chrome 70+.
„ nowa tablica ( % ARR_LENGTH% ) ” - 100% (szybciej) !
„ [] ” - 160–170% (wolniej)
Test można znaleźć tutaj - https://jsperf.com/small-arr-init-with-known-length-brackets-vs-new-array/2
Uwaga: ten wynik został przetestowany w przeglądarce Google Chrome v.70 + ; w Firefox v.70 i IE oba warianty są prawie równe.
źródło