Jaka jest różnica między „Array ()” a „[]” podczas deklarowania tablicy JavaScript?


841

Jaka jest prawdziwa różnica między deklarowaniem tablicy takiej jak ta:

var myArray = new Array();

i

var myArray = [];

[]Token: ARRAY_INIT; new Arraytokeny: NEW, IDENTIFIER; new Array()tokeny:NEW, IDENTIFIER, CALL
noobninja

Odpowiedzi:


951

Jest różnica, ale w tym przykładzie nie ma różnicy.

Używając bardziej szczegółowej metody: new Array()ma jedną dodatkową opcję w parametrach: jeśli przekażesz liczbę do konstruktora, otrzymasz tablicę o tej długości:

x = new Array(5);
alert(x.length); // 5

Aby zilustrować różne sposoby tworzenia tablicy:

var a = [],            // these are the same
    b = new Array(),   // a and b are arrays with length 0

    c = ['foo', 'bar'],           // these are the same
    d = new Array('foo', 'bar'),  // c and d are arrays with 2 strings

    // these are different:
    e = [3]             // e.length == 1, e[0] == 3
    f = new Array(3),   // f.length == 3, f[0] == undefined

;

Kolejna różnica polega na tym, że podczas używania new Array()możesz ustawić rozmiar tablicy, co wpływa na rozmiar stosu. Może to być przydatne, jeśli występują przepełnienia stosu ( Wydajność Array.push vs. Array.unshift ), co dzieje się, gdy rozmiar tablicy przekracza rozmiar stosu i należy go ponownie utworzyć. Tak więc, w zależności od przypadku użycia, może wystąpić wzrost wydajności, new Array()ponieważ można zapobiec przepełnieniu.

Jak wskazano w tej odpowiedzi , new Array(5)tak naprawdę nie doda pięciu undefinedelementów do tablicy. Po prostu dodaje miejsce na pięć przedmiotów. Należy pamiętać, że korzystanie z Arraytej metody utrudnia poleganie na array.lengthobliczeniach.


66
To trochę źle. Jest jedna bardzo ważna różnica między new Array () a [], które rozwinę w mojej odpowiedzi.
coderjoe

30
Ale jak zauważono w odpowiedzi, jest inaczej tylko wtedy, gdy jesteś całkowicie szalony i zastępujesz funkcję Array ..?
nickf

19
Ważne jest to, że użycie nowego operatora powoduje, że interpreter podejmuje wszelkie dodatkowe kroki, aby przejść do zasięgu globalnego, szuka konstruktora, wywołuje konstruktor i przypisuje wynik ... który w większości przypadków będzie tablica środowiska wykonawczego. Możesz uniknąć nakładów związanych z poszukiwaniem globalnego konstruktora, po prostu używając []. Może wydawać się niewielki, ale gdy grasz w aplikacji w celu uzyskania wydajności zbliżonej do czasu rzeczywistego, może to mieć znaczenie.
coderjoe

5
Istnieje ogromna różnica w wydajności: jsperf.com/create-an-array-of-initial-size/2
Marco Luglio

4
To prawda, ale w większości miejsc, w których je dodam, nie potrzebujesz również średników ani podziałów linii. Chodzi o spójność i czytelność. Wiesz, IMHO.
nickf

774

Różnica między tworzeniem tablicy za pomocą tablicy niejawnej a konstruktorem tablicy jest subtelna, ale ważna.

Podczas tworzenia tablicy za pomocą

var a = [];

Mówisz tłumaczowi, aby utworzył nową tablicę wykonawczą. Żadne dodatkowe przetwarzanie w ogóle nie jest konieczne. Gotowy.

Jeśli użyjesz:

var a = new Array();

Mówisz tłumaczowi, że chcę wywołać konstruktor Arrayi wygenerować obiekt. Następnie przegląda kontekst wykonania, aby znaleźć konstruktora do wywołania, i wywołuje go, tworząc tablicę.

Możesz pomyśleć: „Cóż, to wcale nie ma znaczenia. Są takie same!”. Niestety nie możesz tego zagwarantować.

Weź następujący przykład:

function Array() {
    this.is = 'SPARTA';
}

var a = new Array();
var b = [];

alert(a.is);  // => 'SPARTA'
alert(b.is);  // => undefined
a.push('Woa'); // => TypeError: a.push is not a function
b.push('Woa'); // => 1 (OK)

W powyższym przykładzie pierwsze połączenie ostrzeże „SPARTA”, jak można się spodziewać. Drugi nie. Skończysz na niezdefiniowanym. Zauważysz również, że b zawiera wszystkie natywne funkcje obiektu Array, takie jak push, gdzie inne nie.

Chociaż możesz się spodziewać, że tak się stanie, to po prostu ilustruje fakt, że []to nie to samo, co new Array().

Prawdopodobnie najlepiej jest po prostu użyć, []jeśli wiesz, że chcesz tylko tablicę. Nie sugeruję też chodzenia i redefiniowania Array ...


156
Dobrze wiedzieć, jak sądzę. Jakiego rodzaju osoba
nadpisałaby

159
Masz całkowitą rację. Tylko szaleniec zastąpiłby klasę tablic. Teraz poświęć chwilę i zastanów się nad dodatkową pracą przy użyciu nowej metody Array (), która zmusza interpretera do wspierania tych szaleńców. Po prostu unikam tego wszystkiego razem z [].
coderjoe

51
Dobry przykład globalnego zanieczyszczenia, które jest możliwe dzięki JavaScript.
David Snabel-Caunt

8
Warto zauważyć, że nowa tablica (rozmiar) jest szybsza niż inne możliwe metody wykorzystujące notację []. Źródło: jsperf.com/create-an-array-of-initial-size/2
Marco Luglio

9
Niestety ten test jest nieprawidłowo przygotowany. Testuje inicjalizację macierzy za pomocą inicjalizacji macierzy, a następnie dostępu do macierzy. Nie ma żadnej kontroli, aby udowodnić, że przeglądarki rzeczywiście wstępnie przydzielają pamięć (czego nie mówi specyfikacja). Jeśli możemy założyć, że dostęp do tablicy jest stały i większość czasu będzie poświęcana na przydzielanie pamięci w obu przykładach, wtedy [] może być bardziej wskazane, jeśli tworzysz miliony tablic. jsperf.com/array-instancome
coderjoe 30.01.2013

95

Istnieje ważna różnica, o której jeszcze nie wspomniano w żadnej odpowiedzi.

Od tego:

new Array(2).length           // 2
new Array(2)[0] === undefined // true
new Array(2)[1] === undefined // true

Możesz myśleć, że to new Array(2)jest równoważne [undefined, undefined], ale NIE jest!

Spróbujmy z map():

[undefined, undefined].map(e => 1)  // [1, 1]
new Array(2).map(e => 1)            // "(2) [undefined × 2]" in Chrome

Widzieć? Semantyka jest zupełnie inna! Dlaczego tak jest?

Zgodnie z ES6 Spec 22.1.1.2, zadaniem Array(len)jest po prostu tworzenie nowej tablicy, której właściwość lengthjest ustawiona na argument leni to wszystko, co oznacza, że ​​nie ma żadnego prawdziwego elementu w tej nowo utworzonej tablicy.

Funkcja map(), zgodnie ze specyfikacją 22.1.3.15, najpierw sprawdza, HasPropertya następnie wywołuje oddzwonienie, ale okazuje się, że:

new Array(2).hasOwnProperty(0) // false
[undefined, undefined].hasOwnProperty(0) // true

I dlatego nie można oczekiwać, że jakiekolwiek funkcje iterujące będą działać normalnie na tablicach utworzonych znew Array(len) .

BTW, Safari i Firefox mają znacznie lepsze „drukowanie” w tej sytuacji:

// Safari
new Array(2)             // [](2)
new Array(2).map(e => 1) // [](2) 
[undefined, undefined]   // [undefined, undefined] (2) 

// Firefox
new Array(2)             // Array [ <2 empty slots> ]
new Array(2).map(e => 1) // Array [ <2 empty slots> ]
[undefined, undefined]   // Array [ undefined, undefined ]

Już przesłałem problem do Chromium i poprosiłem go o naprawienie tego mylącego drukowania: https://bugs.chromium.org/p/chromium/issues/detail?id=732021

AKTUALIZACJA: Jest już naprawione. Chrome jest teraz drukowany jako:

new Array(2)             // (2) [empty × 2]

22
Twoja jest jedyną faktyczną odpowiedzią
Victor

To ma sens, właśnie wpadłem na inną konstrukcję, dla której nie mogę znaleźć udokumentowanych odniesień: [...Array(2)]co jest równoważne [undefined, undefined]z punktu widzenia wyników.
Roberto Andrade,

Wygląda na to, że odpowiedzią na moje poprzednie komentarze jest „Operator rozprzestrzeniania się”: javascript.info/rest-parameters-spread-operator
Roberto Andrade

@RobertoAndrade ma to sens, ponieważ operator rozkładania będzie musiał odczytać wpisy, aby mógł zastosować takie kopiowanie ... i odczytać taki pusty powrót do slotu undefinedjak zwykle.
Hux

51

Co dziwne, new Array(size)jest prawie dwa razy szybszy niż []w Chrome i mniej więcej taki sam w FF i IE (mierzony poprzez utworzenie i wypełnienie tablicy). Ma to znaczenie tylko wtedy, gdy znasz przybliżony rozmiar tablicy. Jeśli dodasz więcej elementów niż podana długość, zwiększenie wydajności zostanie utracone.

Dokładniej: Array(jest to szybka operacja w stałym czasie, która nie przydziela pamięci, wheras []jest liniową operacją w czasie, która ustawia typ i wartość.


3
Dużo testowałem w Node.js: kiedy trzeba umieścić pewną ilość elementów w tablicy, new Array(length)na 0 <= rozmiar <= ~ 1000, na rozmiar> ~ 1000 wygrywa[]
glukki


40

Aby uzyskać więcej informacji, na następnej stronie opisano, dlaczego nigdy nie musisz go używaćnew Array()

Nigdy nie musisz używać new Object()w JavaScript. {} Zamiast tego użyj literału obiektu . Podobnie nie używaj new Array(), [] zamiast tego użyj literału tablicowego . Tablice w JavaScript działają podobnie jak tablice w Javie, a użycie składni podobnej do Java dezorientuje.

Nie używać new Number, new Stringlub new Boolean. Te formy powodują niepotrzebne zawijanie obiektów. Zamiast tego używaj prostych literałów.

Zobacz także komentarze - new Array(length)formularz nie służy żadnemu przydatnemu celowi (przynajmniej w dzisiejszych implementacjach JavaScript).


3
Crockford również mówi, aby używać [] zamiast nowej Array (). Niestety nie mówi dlaczego w linkowanym artykule. Zakładam, że to tylko kwestia przestrzeni i prędkości. javascript.crockford.com/code.html
Nosredna

4
Crockford nie jest fanem używania słowa kluczowego „new” do tworzenia nowej instancji obiektu w JavaScript. W wykładach stwierdził, że wierzy, że powoduje to dwuznaczność i nie pasuje do dziedziczenia prototypowego stylu Javascript. W szczególności odnosi się do konstruktorów obiektów tworzonych przez użytkowników, ale biorąc pod uwagę to przekonanie, łatwo zrozumieć, dlaczego zaleciłby, aby nie używać go również z wbudowanymi, gdy istnieje alternatywna składnia.
Alan Storm

@Alan Storm: przynajmniej dla Number, String i Boolean mówi, że „te formy powodują niepotrzebne zawijanie obiektów”, ale myślę, że nie dotyczyłoby to Array.
BarelyFitz

10

Aby lepiej zrozumieć []i new Array():

> []
  []
> new Array()
  []
> [] == []
  false
> [] === []
  false
> new Array() == new Array()
  false
> new Array() === new Array()
  false
> typeof ([])
  "object"
> typeof (new Array())
  "object"
> [] === new Array()
  false
> [] == new Array()
  false

Powyższy wynik pochodzi z konsoli Google Chrome w systemie Windows 7.


4
ale dlaczego [] == [] lub [] === [] false?
anu

5
„Wyrażenie porównujące obiekty jest prawdziwe tylko wtedy, gdy operandy odnoszą się do tego samego obiektu.” (źródło: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… )
srph

Ta odpowiedź wybiera przykłady, które sugerują, że oba konstrukty są identyczne. Inne posty na tej stronie wskazują różnice, takie jak Array(3)lub new Array(3)nie jest taki sam jak [3].
ggorlen

8

Pierwszy to domyślne wywołanie konstruktora obiektów. Możesz użyć jego parametrów, jeśli chcesz.

var array = new Array(5); //initialize with default length 5

Drugi daje możliwość utworzenia niepustej tablicy:

var array = [1, 2, 3]; // this array will contain numbers 1, 2, 3.

1
Możesz zrobić to samo z pełnym konstruktorem: var array = new Array (1, 2, 3);
nickf

Więc myślę, że możesz to zrobić var array = [5]za pomocą nawiasów kwadratowych, ale nie używając konstruktora, ponieważ var array = Array(5)tworzy pustą tablicę 5 elementów.
cdmckay

cdmckay - to nieprawda. var a = [5] byłby tablicą z jednym elementem - liczbą pięć.
BarelyFitz

2
@BarelyFitz: Tak powiedziałem. W odpowiedzi Bogdansa mówi, że wywołanie konstruktora nie może być użyte do zainicjowania tablicy, ale się mylił. Mój komentarz miał jedynie wyjaśnić, że nie można użyć wywołania konstruktora do zainicjowania tablicy pojedynczego elementu.
cdmckay

1
@cdmckay: przepraszam, źle zrozumiałem twój komentarz. Wyjaśnienie: new Array (arg) - jeśli argument jest liczbowy, tworzy pustą tablicę o długości = arg; new Array (arg1, arg2) - tworzy nową tablicę i inicjuje elementy tablicy. Więc jeśli chcesz utworzyć tablicę z jednym elementem liczbowym, takim jak [5], nie możesz tego zrobić za pomocą nowego Array (5). Ale tak naprawdę nigdy nie powinieneś używać nowej Array (), więc jest to kwestia sporna.
BarelyFitz

5

Mogę wyjaśnić w bardziej konkretny sposób, zaczynając od tego przykładu opartego na dobrym przykładzie Fredrika.

var test1 = [];
test1.push("value");
test1.push("value2");

var test2 = new Array();
test2.push("value");
test2.push("value2");

alert(test1);
alert(test2);
alert(test1 == test2);
alert(test1.value == test2.value);

Właśnie dodałem kolejną wartość do tablic i wysłałem cztery alarmy: pierwszy i drugi mają dać nam wartość przechowywaną w każdej tablicy, aby mieć pewność co do wartości. Zwrócą to samo! Teraz wypróbuj trzeci, zwraca false, to dlatego, że

JS traktuje test1 jako ZMIENNY z typem danych tablicy , i traktuje test2 jako OBIEKT z funkcjonalnością tablicy , a tutaj jest kilka drobnych różnic.

Pierwszą różnicą jest to, że gdy wywołujemy test1, to wywołuje zmienną bez zastanowienia, po prostu zwraca wartości zapisane w tej zmiennej bez względu na jej typ danych! Ale kiedy wywołujemy test2, wywołuje on funkcję Array (), a następnie przechowuje nasze wartości „Push” we właściwości „Value” , i to samo dzieje się, gdy ostrzegamy test2, zwraca właściwość „Value” obiektu tablicy.

Kiedy więc sprawdzimy, czy test1 jest równy test2, oczywiście nigdy nie zwrócą wartości true, jedna jest funkcją, a druga zmienną (z rodzajem tablicy), nawet jeśli mają tę samą wartość!

Aby się upewnić, wypróbuj 4. alert z dodaną wartością .value; zwróci prawdę. W takim przypadku mówimy JS „Niezależnie od typu kontenera, czy był to funkcja czy zmienna, porównaj wartości przechowywane w każdym kontenerze i powiedz nam, co widziałeś!” dokładnie tak się dzieje.

Mam nadzieję, że jasno wyraziłem ten pomysł i przepraszam za mój zły angielski.


19
To niesamowite, że przegłosowano tak kompletny i kompletny nonsens. Porównanie tablic będzie fałszywe bez względu na to, jak je utworzysz, ponieważ porównuje tożsamość obiektu i są to różne obiekty. Tablice nie mają właściwości wartości. []i new Array()jest identyczny; .valuebędzie undefinedw obu przypadkach, a porównywanie ich zawsze będzie fałszywe.
slikts

Zgadzam się, ta odpowiedź nie ma sensu i niczego nie pokazuje. Nie ma czegoś takiego jak array.value. i oba typeof []i typeof new Array()powrotu object. Jest to jeden z powodów, dla których istnieje funkcja o nazwieArray.isArray
gman

4

Nie ma różnicy przy inicjalizacji tablicy bez jakiejkolwiek długości. Więc var a = []& var b = new Array()jest taki sam.

Ale jeśli zainicjujesz tablicę o długości podobnej var b = new Array(1);, ustawi ona długość obiektu tablicy na 1. Więc jest to odpowiednik var b = []; b.length=1;.

Będzie to problematyczne za każdym razem, gdy wykonasz array_object.push, dodasz element po ostatnim elemencie i zwiększysz długość.

var b = new Array(1);
b.push("hello world");
console.log(b.length); // print 2

vs

var v = [];
a.push("hello world");
console.log(b.length); // print 1

3

Pierwszym z nich jest domyślne wywołanie konstruktora obiektów. Używane głównie do wartości dynamicznych.

var array = new Array(length); //initialize with default length

druga tablica jest używana podczas tworzenia wartości statycznych

var array = [red, green, blue, yellow, white]; // this array will contain values.

3

Nie ma dużej różnicy, w zasadzie robią to samo, ale robią to na różne sposoby, ale czytaj dalej, spójrz na to oświadczenie na W3C:

var cars = ["Saab", "Volvo","BMW"];

i

var cars = new Array("Saab", "Volvo", "BMW");

Dwa powyższe przykłady robią dokładnie to samo. Nie ma potrzeby używania nowego Array ().
Dla uproszczenia, czytelności i szybkości wykonania użyj pierwszej (metoda dosłowna tablicowa).

Ale jednocześnie tworzenie nowej tablicy przy użyciu new Arrayskładni uważanej za złą praktykę:

Unikaj nowej macierzy ()

Nie ma potrzeby korzystania z wbudowanego w JavaScript konstruktora tablic new Array ().
Zamiast tego użyj [].
Te dwie różne instrukcje tworzą nową pustą tablicę o nazwie punkty:

var points = new Array();         // Bad
var points = [];                  // Good 

Te dwie różne instrukcje tworzą nową tablicę zawierającą 6 liczb:

var points = new Array(40, 100, 1, 5, 25, 10); // Bad    
var points = [40, 100, 1, 5, 25, 10];          // Good

Nowy kluczowe komplikuje tylko kod. Może także dawać nieoczekiwane wyniki:

var points = new Array(40, 100);  // Creates an array with two elements (40 and 100)

Co się stanie, jeśli usunę jeden z elementów?

var points = new Array(40);       // Creates an array with 40 undefined elements !!!!!

Więc zasadniczo nie jest uważany za najlepszą praktykę, jest też jedna drobna różnica, możesz podać długość, aby new Array(length)to polubić, co również nie jest zalecanym sposobem.


Cześć Alireza, czy są one gdzieś kopiowane i wklejane? Dodaj link do strony, z której kopiowany jest tekst. Szczegółowe informacje można znaleźć na tej stronie Centrum pomocy . Dziękuję Ci.
Pang

Przydatnenew Array(40).fill(123)
gman

2

Różnica użycia

var arr = new Array(size);

Lub

arr = [];
arr.length = size;

Jak już zostało wystarczająco omówione w tym pytaniu.

Chciałbym dodać problem prędkości - obecnie najszybszym sposobem google chromejest drugi.

Ale zwróć uwagę, te rzeczy często zmieniają się wraz z aktualizacjami. Również czas działania będzie różny dla różnych przeglądarek.

Na przykład - druga opcja, o której wspomniałem, działa przy 2 milionach [operacji / sekundę] chrome, ale jeśli spróbujesz mozilla dev., otrzymasz zaskakująco wyższą stawkę 23 milionów.

W każdym razie sugeruję, abyś sprawdzał to, co jakiś czas, w różnych przeglądarkach (i maszynach), używając witryny jako takiej


2

Jak znam diference u można znaleźć kawałek (lub inne funcitons Array), jak kod1 .i code2 pokazać u Array i jego wystąpienia :

kod1:

[].slice; // find slice here
var arr = new Array();
arr.slice // find slice here
Array.prototype.slice // find slice here

kod2:

[].__proto__ == Array.prototype; // true
var arr = new Array();
arr.__proto__ == Array.prototype; // true

wniosek:

jak możesz zobaczyć []i new Array()utworzyć nową instancję Array. I oni wszyscy otrzymują prototypowe funkcje odArray.prototype

Są po prostu inną instancją Array. Więc to wyjaśnia dlaczego [] != []

:)


2

Dziwnie się zachowałem, używając [].

Mamy „klasy” modelu z polami zainicjowanymi do pewnej wartości. Na przykład:

require([
  "dojo/_base/declare",
  "dijit/_WidgetBase",
], function(declare, parser, ready, _WidgetBase){

   declare("MyWidget", [_WidgetBase], {
     field1: [],
     field2: "",
     function1: function(),
     function2: function()
   });    
});

Odkryłem, że po zainicjowaniu pól []będą one współdzielone przez wszystkie obiekty Modelu. Wprowadzanie zmian w jednym wpływa na wszystkie pozostałe.

Nie zdarza się to przy ich inicjowaniu new Array(). To samo dotyczy inicjalizacji obiektów (w {}porównaniu z nowymi Object())

TBH Nie jestem pewien, czy jest to problem z używanym frameworkiem ( Dojo )


2

Jest w tym coś więcej niż na pierwszy rzut oka. Większość innych odpowiedzi jest poprawnych, ALE TAKŻE ..

new Array(n)

  • Pozwala silnikowi na realokację miejsca dla nelementów
  • Zoptymalizowany do tworzenia tablic
  • Utworzona tablica jest oznaczona jako rzadka, która ma najmniej wydajne operacje tablicowe, ponieważ każdy dostęp do indeksu musi sprawdzać granice, sprawdzać, czy istnieje wartość i kroczyć łańcuchem prototypów
  • Jeśli tablica jest oznaczona jako rzadka, nie ma odwrotu (przynajmniej w wersji 8), zawsze będzie wolniejsza przez cały okres użytkowania, nawet jeśli zapełnisz ją zawartością (spakowana tablica) 1 ms lub 2 godziny później, nie ma znaczenia

[1, 2, 3] || []

  • Utworzona tablica jest oznaczona jako spakowana (chyba że używasz deletelub [1,,3]składnia)
  • Zoptymalizowane dla tablicy operacji ( for .., forEach, map, etc.)
  • Silnik musi ponownie przydzielić przestrzeń wraz ze wzrostem macierzy

To chyba nie jest przypadek dla starszych przeglądarek wersji / przeglądarek.


-2

Znalazłem jedną różnicę między tymi dwiema konstrukcjami, które mocno mnie ugryzły.

Powiedzmy, że mam:

function MyClass(){
  this.property1=[];
  this.property2=new Array();
};
var MyObject1=new MyClass();
var MyObject2=new MyClass();

W prawdziwym życiu, jeśli to zrobię:

MyObject1.property1.push('a');
MyObject1.property2.push('b');
MyObject2.property1.push('c');
MyObject2.property2.push('d');

Skończyłem z tym:

MyObject1.property1=['a','c']
MyObject1.property2=['b']
MyObject2.property1=['a','c']
MyObject2.property2=['d']

Nie wiem, co ma powiedzieć specyfikacja języka, ale jeśli chcę, aby moje dwa obiekty miały unikalne tablice właściwości w moich obiektach, muszę użyć new Array().


Ten JSFiddle pokazuje, że wynik jest taki, jak można się spodziewać po literałach tablicy []i new Array()konstruktorze, co daje jeden element na tablicę na właściwość. Musisz mieć coś innego w swoim kodzie, aby skończyć z wynikiem, który pokazałeś powyżej.
gfullam

Bucky, to się nie zdarza w żadnej przeglądarce. Aby uzyskać takie zachowanie, musisz zrobić coś takiego: var property1static=[]; function MyClass(){ this.property1=property1static; this.property2=new Array(); };
Dave Burton

-3

Użycie konstruktora Array tworzy nową tablicę o pożądanej długości i zapełnia każdy indeks niezdefiniowanym, przypisana tablica do zmiennej tworzy indeksy, dla których podajesz informacje.


1
Nie, tablica NIE jest zapełniona, wewnątrz nie ma indeksu / kluczy. Na przykład .forEach nie działa.
CFrei
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.