Większość samouczków, które przeczytałem o tablicach w JavaScript (w tym w3schools i devguru ) sugerują, że możesz zainicjować tablicę o określonej długości, przekazując liczbę całkowitą do konstruktora Array przy użyciu var test = new Array(4);
składni.
Po swobodnym użyciu tej składni w moich plikach js, uruchomiłem jeden z tych plików przez jsLint i to przeraziło :
Błąd: Problem w wierszu 1 znak 22: Oczekiwano „)” i zamiast tego zobaczył „4”.
var test = new Array (4);
Problem w wierszu 1 znak 23: Oczekiwany ';' i zamiast tego zobaczyłem „)”.
var test = new Array (4);
Problem w wierszu 1 znak 23: Oczekiwano identyfikatora i zamiast tego zobaczyłem „)”.
Po przeczytaniu wyjaśnienia jego zachowania przez jsLint , wygląda na to, że jsLint tak naprawdę nie lubi new Array()
składni, a zamiast tego woli []
przy deklarowaniu tablic.
Mam więc kilka pytań:
Po pierwsze dlaczego? Czy ryzykuję, używając new Array()
zamiast tego składni? Czy są jakieś niezgodności przeglądarki, o których powinienem wiedzieć?
Po drugie, jeśli przejdę do składni nawiasu kwadratowego, czy istnieje sposób zadeklarowania tablicy i ustawienia jej długości w jednym wierszu, czy też muszę zrobić coś takiego:
var test = [];
test.length = 4;
źródło
new Array()
w ogóle, ale to w porządku z określeniem wielkości. Myślę, że wszystko sprowadza się do spójności kodu w całym kontekście.Odpowiedzi:
Dlaczego chcesz zainicjować długość? Teoretycznie nie ma takiej potrzeby. Może to nawet powodować mylące zachowanie, ponieważ wszystkie testy, które używają
length
do sprawdzenia, czy tablica jest pusta, czy nie, zgłoszą, że tablica nie jest pusta.Niektóre testy pokazują, że ustawienie początkowej długości dużych tablic może być bardziej wydajne, jeśli tablica zostanie następnie wypełniona, ale wzrost wydajności (jeśli występuje) wydaje się różnić w zależności od przeglądarki.
jsLint nie lubi,
new Array()
ponieważ konstruktor jest niejednoznaczny.tworzy pustą tablicę o długości 4. Ale
tworzy tablicę zawierającą wartość
'4'
.W odniesieniu do komentarza: w JS nie trzeba inicjować długości tablicy. Rośnie dynamicznie. Możesz po prostu zapisać długość w jakiejś zmiennej, np
źródło
for
pętlę, która iteruje na całej długości tablicy i wypełnia ją. Sądzę, że istnieją inne sposoby na zrobienie tego w JavaScript, więc prawdziwa odpowiedź na pytanie „Dlaczego chcę to zrobić?” to „Ze względu na stare nawyki, które kształtowały się podczas programowania w innych językach”. :)new Array(10)
nie tworzy tablicy z 10 niezdefiniowanymi elementami. Po prostu tworzy pustą tablicę o długości 10. Zobacz tę odpowiedź dla paskudnej prawdy: stackoverflow.com/questions/18947892/...Array(5)
daje tablicę o długości 5, ale bez wartości, dlatego nie można jej iterować.Array.apply(null, Array(5)).map(function () {})
daje tablicę o długości 5 i niezdefiniowaną jako wartości, teraz można ją powtarzać.Array.apply(null, Array(5)).map(function (x, i) { return i; })
daje tablicę o długości 5 i wartościach 0,1,2,3,4.Array(5).forEach(alert)
nic nie robi,Array.apply(null, Array(5)).forEach(alert)
daje 5 alertówES6
daje namArray.from
więc teraz możesz także użyćArray.from(Array(5)).forEach(alert)
Jeśli chcesz zainicjować z pewnej wartości, są dobrze wie ...
Array.from('abcde')
,Array.from('x'.repeat(5))
lub
Array.from({length: 5}, (v, i) => i) // gives [0, 1, 2, 3, 4]
źródło
Array
podano wiele argumentów, iterujearguments
obiekt i jawnie stosuje każdą wartość do nowej tablicy. Kiedy wywołujeszArray.apply
tablicę lub obiekt o właściwości length,Array
użyje długości, aby jawnie ustawić każdą wartość nowej tablicy. DlategoArray(5)
daje tablicę 5 elekcji, aArray.apply(null, Array(5))
tablicę 5 niezdefiniowanych. Aby uzyskać więcej informacji, zobacz tę odpowiedź.Array.apply(null, Array(5))
Można również zapisać jakoArray.apply(null, {length: 5})
. Naprawdę nie ma dużej różnicy, ale ta ostatnia jest jednoznacznie jasna, że celem jest stworzenie tablicylength 5
, a nie tablicy zawierającej5
Dzięki ES2015
.fill()
możesz teraz po prostu zrobić:Co jest o wiele bardziej zwięzłe niż
Array.apply(0, new Array(n)).map(i => value)
Jest to możliwe do spadku
0
w.fill()
i uruchomić bez argumentów, które wypełni tablicę zundefined
. ( Jednak nie powiedzie się to w maszynopisie )źródło
When Array is called as a function rather than as a constructor, it also creates and initializes a new Array object. Thus the function call Array(…) is equivalent to the object creation expression new Array(…) with the same arguments
Array(n).fill()
LUB
Uwaga: nie można zapętlać pustych miejsc, tj
Array(4).forEach(() => …)
LUB
( bezpieczny dla maszynopisu )
LUB
Klasyczna metoda wykorzystująca funkcję (działa w dowolnej przeglądarce)
Tworzenie zagnieżdżonych tablic
Podczas tworzenia tablicy 2D
fill
intuicyjnie należy tworzyć nowe wystąpienia. Ale to, co faktycznie się stanie, to ta sama tablica będzie przechowywana jako odniesienie.Rozwiązanie
Tak więc tablica 3x2 będzie wyglądać mniej więcej tak:
Tablica N-wymiarowa
Zainicjuj szachownicę
źródło
a[0].push(9);
// [ [6, 9], [6], [6] ]
powinno być,a[0].push(9);
// [ [6, 9], [6, 9], [6, 9] ]
ponieważ każda zagnieżdżona tablica jest przechowywana jako odwołanie, więc mutacja jednej tablicy wpływa na resztę. Być może właśnie go źleNajkrótszy:
źródło
[
bez użycia,;
ponieważ będzie ona próbowała wyłuskać linię powyżej. Bezpiecznym sposobem użycia tej linii w przewidywalny sposób w dowolnej części kodu byłoby:;[...Array(1000)]//.whateverOpsNeeded()
[...Array(5)].map((item, index) => ({ index }))
spróbuj również tego:[...Array(5)]; console.log('hello');
const a = 'a'
i następna linia[...Array(5)].//irrelevent
. Jak myślisz, co rozwiązałoby pierwsza linia? Byłoby to,const a = 'a'[...Array(5)]
co skutkowałoby:Uncaught SyntaxError: Unexpected token ...
const a = 'a'
w takim przypadku wystąpi błąd Lint. W każdym razie tak naprawdę nie ma to nic wspólnego z tą odpowiedzią.ES6 wprowadza,
Array.from
który pozwala tworzyćArray
z dowolnych obiektów „podobnych do tablicy” lub iterowalnych :W tym przypadku
{length: 10}
reprezentuje minimalną definicję obiektu „podobnego do tablicy” : pusty obiekt zelength
zdefiniowaną tylko właściwością.Array.from
pozwala na odwzorowanie drugiego argumentu na wynikową tablicę.źródło
Spowoduje to zainicjowanie właściwości length na 4:
źródło
var size = 42; var myArray = eval("["+",".repeat(size)+"]");
? (Nie aż tak poważne;)Dziwi mnie, że nie zaproponowano funkcjonalnego rozwiązania, które pozwala ustawić długość w jednej linii. Poniższe informacje oparte są na UnderscoreJS:
Z powodów wymienionych powyżej unikałbym tego, chyba że chciałbym zainicjować tablicę do określonej wartości. Warto zauważyć, że istnieją inne biblioteki, które implementują zakres, w tym Lo-dash i Lazy, które mogą mieć różne charakterystyki wydajności.
źródło
Proszę, ludzie jeszcze nie rezygnują z twoich starych nawyków. Istnieje duża różnica w szybkości między alokowaniem pamięci raz, a następnie pracą z wpisami w tej tablicy (jak na starym), i alokowaniem jej wiele razy w miarę wzrostu tablicy (co jest nieuchronnie tym, co system robi pod maską za pomocą innych sugerowanych metod) .
Nie ma to oczywiście znaczenia, dopóki nie chcesz zrobić czegoś fajnego z większymi tablicami. To robi.
Ponieważ w JS wciąż nie ma opcji ustawienia początkowej pojemności macierzy, używam następujących ...
W grę wchodzą kompromisy:
standard
Tablica ma stałe zarezerwować tyle miejsca, co do wielkości tablicy ty prosić.Ale jeśli pasuje to do tego, co robisz, może być to opłacalne. Nieformalny czas stawia
przy dość szybkim czasie (około 50 ms dla 10000, biorąc pod uwagę, że przy n = 1000000 zajęło to około 5 sekund), i
znacznie ponad minutę (około 90 sekund dla 10000 na tej samej konsoli chromowanej lub około 2000 razy wolniej). To nie będzie tylko alokacja, ale także 10000 wypychań dla pętli itp.
źródło
(prawdopodobnie było to lepsze jako komentarz, ale stało się za długie)
Po przeczytaniu tego zastanawiałem się, czy wstępne przydzielanie było faktycznie szybsze, ponieważ teoretycznie powinno być. Jednak ten blog zawiera kilka wskazówek odradzających go http://www.html5rocks.com/en/tutorials/speed/v8/ .
Wciąż będąc niepewnym, wystawiam to na próbę. I jak się okazuje, w rzeczywistości wydaje się być wolniejszy.
Ten kod daje następujące wyniki po kilku przypadkowych uruchomieniach:
źródło
źródło
[5: 0]
że jest to rzadka tablica i prawdopodobnie nie to, co jest potrzebne.Oto inne rozwiązanie
Pierwszym argumentem
apply()
jest powiązanie tego obiektu, na którym nam nie zależy, więc ustawiliśmy to nanull
.Array.apply(..)
wywołujeArray(..)
funkcję i rozkłada{ length: 3 }
wartość obiektu jako argumenty.źródło
new Array(n)
do zainicjowania takiej tablicynew Array(n).map(function(notUsed,index){...})
, ale przy takim podejściu, jak wspomniano @zangw, można to zrobić. +1 ode mnieKonstruktor tablic ma niejednoznaczną składnię , a JSLint po prostu rani twoje uczucia.
Ponadto twój przykładowy kod jest uszkodzony, druga
var
instrukcja podniesie aSyntaxError
. Ustawiasz właściwośćlength
tablicytest
, więc nie ma potrzeby kolejnejvar
.Jeśli chodzi o opcje,
array.length
jest to jedyna „czysta”. Pytanie brzmi: dlaczego musisz najpierw ustawić rozmiar? Spróbuj zmodyfikować kod, aby pozbyć się tej zależności.źródło
var test
. To było trochę niechlujne kopiowanie i wklejanie z mojej strony.Zakładając, że długość tablicy jest stała. W JavaScript robimy to:
const intialArray = new Array(specify the value);
źródło
Jak wyjaśniono powyżej, używanie
new Array(size)
jest nieco niebezpieczne. Zamiast używać go bezpośrednio, umieść go w „funkcji twórcy tablicy”. Możesz łatwo upewnić się, że ta funkcja jest wolna od błędów i uniknąć niebezpieczeństwanew Array(size)
bezpośredniego połączenia . Możesz także nadać mu opcjonalną domyślną wartość początkową. TacreateArray
funkcja robi dokładnie to:źródło
W większości odpowiedzi zaleca się
fill
tablicę, ponieważ w przeciwnym razie „nie można iterować” , ale nie jest to prawdą. Możesz iterować pustą tablicę, ale nie za pomocąforEach
. Podczas gdy pętle, pętle for i pętle for działają poprawnie.Nie działa.
Te prace:
Czek to skrzypce z powyższymi przykładami.
Również kąty
*ngFor
działają dobrze z pustą tablicą:źródło
Możesz ustawić długość tablicy za pomocą
array.length = youValue
Tak by było
źródło
Powód, dla którego nie należy używać,
new Array
wynika z tego kodu:Może inny kod zadzierać ze zmienną Array. Wiem, że jest trochę daleko posunięte, że ktoś napisałby taki kod, ale nadal ...
Ponadto, jak powiedział Felix King, interfejs jest nieco niespójny i może prowadzić do bardzo trudnych do wyśledzenia błędów.
Jeśli chcesz tablicę o długości = x, wypełnioną niezdefiniowaną (jak
new Array(x)
by to zrobiło), możesz to zrobić:źródło
alert
iundefined
, ponieważ jakiś inny kod może z nimi zadzierać. Drugi przykład jest mniej czytelnynew Array(4)
i nie daje takiego samego rezultatu: jsfiddle.net/73fKd