Jak zainicjalizować długość tablicy w JavaScript?

Większość samouczków, które czytałem o tablicach w JavaScript (w tym w3schools i devguru) sugeruje, że można zainicjować tablicę o określonej długości, przekazując liczbę całkowitą do konstruktora tablicy przy użyciu składni var test = new Array(4);.

Po użyciu tej składni w moich plikach js, przepuściłem jeden z plików przez jsLint i wyszło:

Error: Problem at line 1 character 22: Expected') ' and instead saw '4'.
var test = new Array (4);
Problem w linii 1 znak 23: Expected'; 'and instead saw')'.
var test = new Array (4);
Problem w linii 1 znak 23: oczekiwał identyfikatora, a zamiast tego zobaczył")".

Po przeczytaniu wyjaśnienia jslinta jego zachowania, wygląda na to, że jsLint nie lubi składni new Array(), a zamiast tego preferuje [] podczas deklarowania tablic.

Więc mam kilka pytań:

Po pierwsze, dlaczego? Czy Ja uruchamianie jakiegokolwiek ryzyka używając zamiast tego składni new Array()? Czy są niezgodności w przeglądarce, o których powinienem wiedzieć?

I po drugie, jeśli przełączę się na składnię nawiasu kwadratowego, czy jest jakiś sposób na zadeklarowanie tablicy i ustawienie jej długości w jednej linii, Czy muszę zrobić coś takiego:

var test = [];
test.length = 4;
Author: simhumileco, 2011-01-31

18 answers

  1. Dlaczego chcesz zainicjować długość? Teoretycznie nie ma takiej potrzeby. Może to nawet spowodować mylące zachowanie, ponieważ wszystkie testy, które używają length, aby dowiedzieć się, czy tablica jest pusta, będą raportować, że tablica nie jest pusta.
    niektóre testy pokazują, że ustawienie początkowej długości dużych tablic Może być bardziej efektywne, jeśli tablica zostanie później wypełniona, ale przyrost wydajności (jeśli występuje) wydaje się różnić w zależności od przeglądarki przeglądarka.

  2. JsLint nie lubi new Array(), ponieważ konstruktor jest niejednoznaczny.

    new Array(4);
    

    Tworzy pustą tablicę o długości 4. Ale

    new Array('4');
    

    Tworzy tablicę zawierającą wartość '4'.

Odnośnie Twojego komentarza: w JS nie musisz inicjalizować długości tablicy. Rośnie dynamicznie. Możesz po prostu zapisać długość w jakiejś zmiennej, np.

var data = [];
var length = 5; // user defined length

for(var i = 0; i < length; i++) {
    data.push(createSomeObject());
}
 439
Author: Felix Kling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-07 15:21:01
  • Array(5) daje tablicę o długości 5, ale bez wartości, dlatego nie można nad nią iteracji.

  • Array.apply(null, Array(5)).map(function () {}) daje tablicę o długości 5 i undefined jako wartości, teraz Można ją iterować.

  • 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 wpisów

  • ES6 daje nam Array.from, więc teraz możesz również użyć Array.from(Array(5)).forEach(alert)

  • Jeśli chcesz inicjalizuj z pewną wartością, dobrze jest to wiedzieć...
    Array.from('abcde'), Array.from('x'.repeat(5))
    lub Array.from({length: 5}, (v, i) => i) // gives [0, 1, 2, 3, 4]

 707
Author: Ruben Stolk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-11 14:01:52

Z ES2015 .fill() możesz teraz po prostu zrobić:

// `n` is the size you want to initialize your array
// `0` is what the array will be filled with (can be any other value)
Array(n).fill(0)

Który jest o wiele bardziej zwięzły niż Array.apply(0, new Array(n)).map(i => value)

Można upuścić 0 w .fill() i uruchomić bez argumentów, które wypełnią tablicę undefined. ( to jednak nie powiedzie się w maszynopisie )

 331
Author: AP.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-09 21:59:35
[...Array(6)].map(x => 0);
// [0, 0, 0, 0, 0, 0]

Lub

Array(6).fill(0);
// [0, 0, 0, 0, 0, 0]

uwaga: nie można zapętlać pustych slotów tj. Array(4).forEach(() => …)


Lub

( typescript safe )

Array(6).fill(null).map((_, i) => i);
// [0, 1, 2, 3, 4, 5]

Lub

Klasyczna metoda wykorzystująca funkcję (działa w dowolnej przeglądarce)

function NewArray(size) {
    var x = [];
    for (var i = 0; i < size; ++i) {
        x[i] = i;
    }
    return x;
}

var a = NewArray(10);
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Tworzenie zagnieżdżonych tablic

Podczas tworzenia 2D tablica z fill intuicyjnie powinna tworzyć nowe instancje. Ale to, co faktycznie się wydarzy, to ta sama tablica będą przechowywane jako odniesienie.

var a = Array(3).fill([6]);
// [  [6], [6], [6]  ]

a[0].push(9);
// [  [6, 9], [6, 9], [6, 9]  ]

Rozwiązanie

var a = [...Array(3)].map(x => []);

a[0].push(4, 2);
// [  [4, 2], [], []  ]

Więc tablica 3x2 będzie wyglądać mniej więcej tak:

[...Array(3)].map(x => Array(2).fill(0));
// [  [0, 0], [0, 0], [0, 0]  ]

Tablica N-wymiarowa

function NArray(...dimensions) {
    var index = 0;
    function NArrayRec(dims) {
        var first = dims[0], next = dims.slice().splice(1); 
        if(dims.length > 1) 
            return Array(dims[0]).fill(null).map((x, i) => NArrayRec(next ));
        return Array(dims[0]).fill(null).map((x, i) => (index++));
    }
    return NArrayRec(dimensions);
}

var arr = NArray(3, 2, 4);
// [   [  [ 0,  1,  2,  3 ] , [  4,  5,  6,  7]  ],
//     [  [ 8,  9,  10, 11] , [ 12, 13, 14, 15]  ],
//     [  [ 16, 17, 18, 19] , [ 20, 21, 22, 23]  ]   ]

Zainicjalizuj szachownicę

var Chessboard = [...Array(8)].map((x, j) => {
    return Array(8).fill(null).map((y, i) => {
        return `${String.fromCharCode(65 + i)}${8 - j}`;
    });
});

// [ [A8, B8, C8, D8, E8, F8, G8, H8],
//   [A7, B7, C7, D7, E7, F7, G7, H7],
//   [A6, B6, C6, D6, E6, F6, G6, H6],
//   [A5, B5, C5, D5, E5, F5, G5, H5],
//   [A4, B4, C4, D4, E4, F4, G4, H4],
//   [A3, B3, C3, D3, E3, F3, G3, H3],
//   [A2, B2, C2, D2, E2, F2, G2, H2],
//   [A1, B1, C1, D1, E1, F1, G1, H1] ]

Wartości wypełnione matematycznie

Poręczne małe przeciążenie metody podczas pracy z matematyką


function NewArray( size , method, linear )
{
    method = method || ( i => i ); 
    linear = linear || false;
    var x = [];
    for( var i = 0; i < size; ++i )
        x[ i ] = method( linear ? i / (size-1) : i );
    return x;
}

NewArray( 4 ); 
// [ 0, 1, 2, 3 ]

NewArray( 4, Math.sin ); 
// [ 0, 0.841, 0.909, 0.141 ]

NewArray( 4, Math.sin, true );
// [ 0, 0.327, 0.618, 0.841 ]

var pow2 = ( x ) => x * x;

NewArray( 4, pow2 ); 
// [ 0, 1, 4, 9 ]

NewArray( 4, pow2, true ); 
// [ 0, 0.111, 0.444, 1 ]
 227
Author: Vlad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-30 15:43:47

Najkrótszy:

let arr = [...Array(10)];
console.log(arr);
 81
Author: Michael Mammoliti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-28 14:37:24

ES6 wprowadza Array.from co pozwala na tworzenie Array z dowolnego"array-like" lubiterables obiektów:

Array.from({length: 10}, (x, i) => i);
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

W tym przypadku {length: 10} reprezentuje minimalną definicję "array-like" obiektu: pustego obiektu o zdefiniowanej właściwości length.

Array.from pozwala na odwzorowanie drugiego argumentu nad wynikową tablicą.

 43
Author: Alexander Shutau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-28 11:26:59

Spowoduje zainicjalizowanie właściwości length na 4:

var x = [,,,,];
 28
Author: Šime Vidas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-31 14:35:14

Dziwię się, że nie zaproponowano funkcjonalnego rozwiązania, które pozwala ustawić długość w jednej linii. Na podstawie podkreślenia opiera się:

var test = _.map(_.range(4), function () { return undefined; });
console.log(test.length);

Z powodów wymienionych powyżej, unikałbym tego, chyba że chciałem zainicjować tablicę do określonej wartości. Warto zauważyć, że istnieją inne biblioteki implementujące range, w tym Lo-dash i Lazy, które mogą mieć różne charakterystyki wydajności.

 16
Author: christang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-23 04:31:44

Oto inne rozwiązanie

var arr = Array.apply( null, { length: 4 } );
arr;  // [undefined, undefined, undefined, undefined] (in Chrome)
arr.length; // 4

Pierwszym argumentem {[1] } jest powiązanie z tym obiektem, które nas tu nie obchodzi, więc ustawiamy je na null.

Array.apply(..) wywołuje funkcję Array(..) i rozkłada wartość obiektu { length: 3 } jako jej argumenty.

 9
Author: zangw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-31 02:01:30

Proszę ludzi, nie rezygnujcie jeszcze ze swoich starych nawyków. Istnieje duża różnica w szybkości między przydzielaniem pamięci raz, a pracą z wpisami w tej tablicy (jak w starej), a przydzielaniem jej wiele razy w miarę wzrostu tablicy (co jest nieuchronnie tym, co system robi pod maską z innymi sugerowanymi metodami).

Nic z tego nie ma oczywiście znaczenia, dopóki nie chcesz zrobić czegoś fajnego z większymi tablicami. Więc tak jest.

Skoro nadal wydaje się, że nie ma opcji w JS na moment, aby ustawić początkową pojemność tablicy, używam następujących...

var newArrayWithSize = function(size) {
  this.standard = this.standard||[];
  for (var add = size-this.standard.length; add>0; add--) {
   this.standard.push(undefined);// or whatever
  }
  return this.standard.slice(0,size);
}

W grę wchodzą:

  • ta metoda zajmuje tyle samo czasu co pozostałe przy pierwszym wywołaniu funkcji, ale bardzo mało czasu na późniejsze wywołania (chyba że poprosi o większą tablicę).
  • tablica standard trwale rezerwuje tyle miejsca, co największa tablica, o którą prosiłeś.
Ale jeśli to pasuje do tego, co robisz, może być wypłata. Nieformalne terminy puts
for (var n=10000;n>0;n--) {var b = newArrayWithSize(10000);b[0]=0;}

W dość szybkim tempie (około 50ms dla 10000 biorąc pod uwagę, że z n=1000000 zajęło to około 5 sekund), i

for (var n=10000;n>0;n--) {
  var b = [];for (var add=10000;add>0;add--) {
    b.push(undefined);
  }
}

W znacznie ponad minutę (około 90 SEK dla 10000 na tej samej konsoli chrome, lub około 2000 razy wolniej). To nie będzie tylko alokacja, ale także 10000 nacisków, pętli for itp..

 9
Author: wils,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-26 01:12:19

(to było chyba lepsze jako komentarz, ale za długo)

Po przeczytaniu tego byłem ciekaw, czy pre-alokacja jest rzeczywiście szybsza, bo teoretycznie powinna być. Jednak ten blog dał kilka wskazówek odradzających to http://www.html5rocks.com/en/tutorials/speed/v8/. Więc wciąż będąc niepewnym, wystawiłem to na próbę. I jak się okazuje, w rzeczywistości wydaje się być wolniejszy.
var time = Date.now();
var temp = [];
for(var i=0;i<100000;i++){
    temp[i]=i;
}
console.log(Date.now()-time);


var time = Date.now();
var temp2 = new Array(100000);
for(var i=0;i<100000;i++){
    temp2[i] = i;
}
console.log(Date.now()-time); 

Ten kod daje następujący po kilku przypadkowych uruchomieniach:

$ node main.js 
9
16
$ node main.js 
8
14
$ node main.js 
7
20
$ node main.js 
9
14
$ node main.js 
9
19
 8
Author: j03m,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-26 14:25:54
var arr=[];
arr[5]=0;
alert("length="+arr.length); // gives 6
 8
Author: user1067305,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-27 23:27:03

Zakładając, że długość tablicy jest stała. W Javascript, to jest to, co robimy:

const intialArray = new Array(specify the value);

 4
Author: mohan babu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-23 03:00:32

Konstruktor tablicy ma dwuznaczną składnię , A JSLint po prostu rani twoje uczucia.

Również, Twój przykładowy kod jest uszkodzony, druga var Instrukcja wywoła SyntaxError. Ustawiasz właściwość length tablicy test, więc nie ma potrzeby stosowania innej var.

Jeśli chodzi o Twoje opcje, array.length jest jedynym "czystym". Pytanie brzmi, dlaczego musisz ustawić rozmiar w pierwszej kolejności? Spróbuj przefaktorować kod, aby pozbyć się tej zależności.

 3
Author: Ivo Wetzel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-04 11:45:29

Jak wyjaśniono powyżej, używanie new Array(size) jest nieco niebezpieczne. Zamiast używać go bezpośrednio, umieść go w "funkcji kreatora tablic". Możesz łatwo upewnić się, że ta funkcja jest wolna od błędów i uniknąć niebezpieczeństwa wywołania new Array(size) bezpośrednio. Możesz również podać opcjonalną domyślną wartość początkową. Ta funkcja createArray robi dokładnie to:

function createArray(size, defaultVal) {
    const arr = new Array(size);
    if (defaultVal !== undefined) {
        // optional default value
        for (let i = 0; i < size; ++i) {
            arr[i] = defaultVal;
        }
    }
    return arr;
}
 2
Author: Domi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-29 06:06:36

W większości odpowiedzi zaleca się użycie tablicy fill, ponieważ w przeciwnym razie "nie można jej iterować", ale to nieprawda. Możesz iterować pustą tablicę, ale nie za pomocą forEach. Podczas gdy pętle, dla pętli i dla i pętle działają dobrze.

const count = Array(5);
Nie działa.
console.log('---for each loop:---');
count.forEach((empty, index) => {
    console.log(`counting ${index}`);
});

Te prace:

console.log('---for of loop:---');
for (let [index, empty] of count.entries()) {
  console.log(`counting for of loop ${index}`);
}

console.log('---for i loop:---');
for (let i = 0, il = count.length; i < il; ++i) {
  console.log(`counting for i loop ${i}`);
}

console.log('---while loop:---');
let index = 0;
while (index < count.length) { 
  console.log(`counting while loop ${index}`); 
  index++; 
}

Sprawdź this fiddle z powyższymi przykładami.

Również angulars *ngFor działa dobrze z pustą tablicą:

<li *ngFor="let empty of count; let i = index" [ngClass]="
  <span>Counting with *ngFor {{i}}</span>
</li>
 1
Author: Wilt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-26 09:32:46

Możesz ustawić długość tablicy używając array.length = youValue

Tak by było

var myArray = [];
myArray.length = yourValue;
 -1
Author: ajoposor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-09 19:33:00

Powód, dla którego nie powinieneś używać new Array jest pokazany w tym kodzie:

var Array = function () {};

var x = new Array(4);

alert(x.length);  // undefined...

Inny kod mógłby pomieszać ze zmienną Array. Wiem, że to trochę naciągane, że ktoś napisze taki kod, ale i tak...

Ponadto, jak powiedział Felix King, interfejs jest trochę 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ą undefined( jak zrobiłby new Array(x)), możesz to zrobić:

var x = 4;
var myArray = [];
myArray[x - 1] = undefined;

alert(myArray.length); // 4
 -3
Author: nickf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-31 14:34:15