forked from BonsaiDen/JavaScript-Garden
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
28 changed files
with
1,969 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
{ | ||
"default": "en", | ||
"listed": ["en", "fi", "ru", "zh", "tr"] | ||
"listed": ["en", "fi", "ru", "zh", "tr", "pl"] | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
## Konstruktor `Array` | ||
|
||
Zaleca się zawsze korzystać z literału tablicy - notacja `[]` - podczas tworzenia | ||
nowych tablic, ponieważ konstruktor `Array` niejednoznacznie interpretuje | ||
parametry do niego przekazane. | ||
|
||
[1, 2, 3]; // Rezultat: [1, 2, 3] | ||
new Array(1, 2, 3); // Rezultat: [1, 2, 3] | ||
|
||
[3]; // Rezultat: [3] | ||
new Array(3); // Rezultat: [] | ||
new Array('3') // Rezultat: ['3'] | ||
|
||
W przypadku gdy tylko jeden argument zostanie przekazany do kostruktora `Array` i | ||
ten argument jest typu `Number`, konstruktor zwróci nową *dziwną* tablicę | ||
z ustawioną właściwością `length` na wartość przekazaną jako argument. Należy | ||
zauważyć, że **tylko** właściwość `length` zostanie ustawiona w ten sposób, | ||
rzeczywiste indeksy w tej tablicy nie zostaną zainicjalizowane. | ||
|
||
var arr = new Array(3); | ||
arr[1]; // undefined | ||
1 in arr; // zwraca false, indeks nie został ustawiony | ||
|
||
Możliwość ustanienia z góry długości tablicy jest użyteczna tylko w kilku | ||
przypadkach, jak powtarzanie ciągu znaków, w którym unika się stosowania | ||
pętli `for`. | ||
|
||
// count - ilosc powtorzen | ||
// stringToRepeat - ciąg znaków do powtórzenia | ||
new Array(count + 1).join(stringToRepeat); | ||
|
||
### Wnioski | ||
|
||
W miare możliwości należy unikać używania konstruktora `Array`. Literały są | ||
zdecydowanie lepszym rozwiązaniem, są krótsze i mają bardziej precyzyjną składnię. | ||
Zwiększają również czytelność kodu. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
## Iterowanie po tablicach oraz właściwości tablic | ||
|
||
Mimo, że tablice w JavaScript są obiektami, nie ma dobrych powodów do używania | ||
[`pętli for in`](#object.forinloop) do iteracji po nich. W rzeczywiści istnieje | ||
wiele dobrych powodów **przeciwko** wykorzystania `for in` na tablicach. | ||
|
||
> **Uwaga:** Tablice JavaScriptowe **nie** są *tablicami asocjacyjnymi*. JavaScript | ||
> posiada tylko [obiekty](#object.general) do mapowania kluczy do wartości. Jednakże | ||
> tablice asocjacyjne **zachowują** porządek, natomiast obiekty **nie zachowują**. | ||
Ponieważ pętla `for in` wylicza wszystkie właściwości, które są wewnątrz | ||
łańcucha prototypów i jedynym sposobem aby wykluczyć te właściwości to użycie | ||
[`hasOwnProperty`](#object.hasownproperty), ale wówczas pętla staje się | ||
**dwadzieście razy** wolniejsza od normalnej pętli `for`. | ||
|
||
### Iteracja | ||
|
||
W celu osiągnięcia najlepszej wydajności podczas iteracji po tablicach należy | ||
użyć klasycznej pętli `for`. | ||
|
||
var list = [1, 2, 3, 4, 5, ...... 100000000]; | ||
for(var i = 0, l = list.length; i < l; i++) { | ||
console.log(list[i]); | ||
} | ||
|
||
Jest tam jeszcze jeden dodatkowy haczyk w przykładzie powyżej. Jest to zbuforowanie | ||
długości tablicy poprzez `l = list.length`. | ||
|
||
Mimo, że właściwość `length` jest zdefiniowana w wewnątrz tablicy, istnieje nadal | ||
dodatkowy koszt na wyszukiwanie tej właściwości przy każdej iteracji w pętli. | ||
Chociaż najnowsze silniki JavaScript **mogą** zastosować optymalizację w tym | ||
przypadku. Nie ma jednak możliwość ustalenia czy kod będzie wykonywany w jednym | ||
z tych nowych silników czy też nie. | ||
|
||
W rzeczywistości pomijając buforowanie długości tablicy może spowodować, że pętla | ||
będzie tylko **w połowie tak szybka** jak ta z buforowaniem długości. | ||
|
||
### Właściwość `length` | ||
|
||
Mimo, że *getter* właściwości `length` po prostu zwraca liczbę elementów, które są | ||
zawarte w tablicy, to *setter* może być użyta do **skracania** tablicy. | ||
|
||
var foo = [1, 2, 3, 4, 5, 6]; | ||
foo.length = 3; | ||
foo; // [1, 2, 3] | ||
|
||
foo.length = 6; | ||
foo; // [1, 2, 3] | ||
|
||
Przypisanie mniejszej długości spowoduje skrócenie tablicy, ale zwiększenie wartości | ||
`length` nie ma żadnego wpływu na tablicę. | ||
|
||
### Wnioski | ||
|
||
Aby uzyskać najlepszą wydajność zaleca się, aby zawsze używać zwykłej pętli `for` | ||
i zbuforowanie właściwości `length`. Korzystanie z pętli `for in` na tablicy jest | ||
znakiem źle napisanego kodu, który jest podatny na błędy i ma słabą wydajność. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
## Dlaczego nie należy używać `eval` | ||
|
||
Funkcja `eval` uruchomi podany string jako kod JavaScript w lokalnym zasięgu (scopie). | ||
|
||
var foo = 1; | ||
function test() { | ||
var foo = 2; | ||
eval('foo = 3'); | ||
return foo; | ||
} | ||
test(); // 3 | ||
foo; // 1 | ||
|
||
Niestaty `eval` zostanie wykonana w lokalnym zasięgu tylko jeżeli została wywołana | ||
**bezpośrednio** *i* nazwa wołanej funkcji równa sie `eval`. | ||
|
||
var foo = 1; | ||
function test() { | ||
var foo = 2; | ||
var bar = eval; | ||
bar('foo = 3'); | ||
return foo; | ||
} | ||
test(); // 2 | ||
foo; // 3 | ||
|
||
Należy unikać stosowania `eval` **o ile to tylko możliwe**. W 99.9% przypadków można | ||
osiągnąć ten sam efekt **nie** używając `eval`. | ||
|
||
### `eval` w przebraniu | ||
|
||
[Funkcje wykonywane po upływie czasu](#other.timeouts) `setTimeout` i `setInterval` | ||
mogą przyjąć string jako pierwszy argument. String ten zostanie **zawsze** wykonany | ||
w globalnym zasięgu, ponieważ funkcja `eval` zostanie wywołana niebezpośrednio w tym | ||
przypadku. | ||
|
||
### Problemy z bezpieczeństwem | ||
|
||
Funkcja `eval` jest również problematyczna od strony bezpieczeństwa, ponieważ | ||
wykonuje **każdy** kod, który zostanie do niej przekazany i nie należy **nigdy** | ||
używać jej na stringach nieznanego lub niezaufanego pochodzenia. | ||
|
||
### Wnioski | ||
|
||
Funkcja `eval` nie powinna być w ogole używana, każdy kod, który ją wykorzystuje | ||
powinien zostać sprawdzony pod względem działania, wydajności i bezpieczeństwa. | ||
W przypadku gdy użycie `eval` jest niezbędne do działania, wówczas taki kod | ||
należy przemyśleć raz jeszcze i *ulepszyć* kod aby nie wymagał użycia `eval`. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
## Automatyczne wstawianie średnika | ||
|
||
Mimo, że JavaScript ma składnię podobną do języka C, to **nie** wymusza stosowania | ||
średników w kodzie źródłowym. Istnieje możliwość ich pominięcia. | ||
|
||
Lecz JavaScript nie jest językiem bez średników, tak na prawdę potrzebuje | ||
średników aby zinterpretować kod źródłowy. Jednakże parser JavaScript | ||
**automatycznie** wstawia średniki o ile napotka błąd parsowania związany z | ||
brakiem średnika. | ||
|
||
var foo = function() { | ||
} // błąd parsowania, oczekiwany był w tym miejscu średnik | ||
test() | ||
|
||
Parser dodaje średnik, i próbuje jeszcze raz sparsować skrypt. | ||
|
||
var foo = function() { | ||
}; // bez błędu parser kontynuuje | ||
test() | ||
|
||
Automatyczne wstawianie średników jest uważane za jeden z **największych** błędów | ||
konstrukcji języka, ponieważ *może* ono zachowanie kodu. | ||
|
||
### Jak działa wstawianie | ||
|
||
Kod poniżej nie ma żadnych średników, więc parser zdecyduje, w których miejscach | ||
je wstawi. | ||
|
||
(function(window, undefined) { | ||
function test(options) { | ||
log('testing!') | ||
|
||
(options.list || []).forEach(function(i) { | ||
|
||
}) | ||
|
||
options.value.test( | ||
'long string to pass here', | ||
'and another long string to pass' | ||
) | ||
|
||
return | ||
{ | ||
foo: function() {} | ||
} | ||
} | ||
window.test = test | ||
|
||
})(window) | ||
|
||
(function(window) { | ||
window.someLibrary = {} | ||
|
||
})(window) | ||
|
||
Poniżej znajduje się rezultat "zgadywania" parsera. | ||
|
||
(function(window, undefined) { | ||
function test(options) { | ||
|
||
// Nie wstaniony średnik, linie zostały połączone | ||
log('testing!')(options.list || []).forEach(function(i) { | ||
|
||
}); // <- wstawiony | ||
|
||
options.value.test( | ||
'long string to pass here', | ||
'and another long string to pass' | ||
); // <- wstawiony | ||
|
||
return; // <- wstawiony, psując deklarację return | ||
{ // potraktowane jako definicja bloku | ||
|
||
// etykieta oraz pojedyncze wyrażenie | ||
foo: function() {} | ||
}; // <- wstawiony | ||
} | ||
window.test = test; // <- wstawiony | ||
|
||
// Kolejna połączona linia | ||
})(window)(function(window) { | ||
window.someLibrary = {}; // <- wstawiony | ||
|
||
})(window); //<- wstawiony | ||
|
||
> **Uwaga:** Parser JavaScript nie potrafił "odpowiednio" zinterpretować | ||
> deklaracji return, po którje został dodany znak nowej linii. Mimo, że | ||
> niekoniecznie jest to błąd automatycznego wstawiania średników, to może to | ||
> jednak powodować niechciane efekty uboczne | ||
Parser drastycznie zmienił działanie powyższego kodu, w niektórych przypadkach | ||
**zmienił go źle**. | ||
|
||
### Nawiasy | ||
|
||
W przypadku, gdy w następnej linii znajduje się nawias, parser **nie** wstawi | ||
średnika. | ||
|
||
log('testing!') | ||
(options.list || []).forEach(function(i) {}) | ||
|
||
Ten kod zostanie zmieniony w poniższą jedną linię. | ||
|
||
log('testing!')(options.list || []).forEach(function(i) {}) | ||
|
||
Jest **bardzo** prawdopodobne, że `log` **nie** zwróci fukcji, co za tym idzie | ||
powyższy kod wyrzuci błąd `TypeError` oznajmując, że `undefined is not a | ||
function` - `undefined` nie jest funkcją. | ||
|
||
### Wnioski | ||
|
||
Zaleca się aby **nigdy** nie pomijać średników, pozostawiać nawias otwierający | ||
w tej samej linii co odpowiadająca mu definicja i nigdy nie pozostawiać deklaracji | ||
`if` / `else` bez nawiasów nawet jeżeli są jednolinijkowe. Wszystkie te uwagi nie | ||
tylko pomagają poprawić spójność kodu, ale również zapobiegają parser JavaScript | ||
przed zmianą działania kod. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
## `undefined` i `null` | ||
|
||
JavaScript ma dwie różne wartości dla `pustych` wartości, bardziej użyteczną | ||
z tych dwóch jest `undefined`. | ||
|
||
### Wartość `undefined` | ||
|
||
`undefined` jest typem z dokładnie jedną wartością: `undefined`. | ||
|
||
Język również definiuje globalną zmienną, która ma wartość `undefined`, zmienna | ||
ta jest nazwana `undefined`. Jednakże jest to zmienna a **nie** stała czy słowo | ||
kluczowe w języku. Oznacza to że możliwe jest nadpisanie *wartości* tej zmiennej. | ||
|
||
> Uwaga ES55: `undefined` w ECMAScript 5 **nie będzie już** *nadpisywalna* w trybie | ||
> strict mode, ale jej nazwa może zostać przysłonona przez na przykład funkcję o | ||
> nazwie `undefined`. | ||
Kilka przykładów kiedy wartość `undefined` jest zwracana: | ||
|
||
- Dostęp do (niemodyfikowalnej) zmiennej globalnej `undefined`. | ||
- Wyjście z funkcji, która nie ma deklaracji `return`. | ||
- Deklaracja `return`, która nic jawnie nie zwraca. | ||
- Poszukiwanie nieistniejącej właściwości. | ||
- Parametr funkcji, który nie został jawnie przekazany podczas wywołania funkcji | ||
- Wszystko co zostało ustawione na wartość `undefined` | ||
|
||
### Obsługa przypadku zmiany wartości `undefined` | ||
|
||
Ponieważ globalna zmienna `undeined` tylko zawiera kopię prawdziwej *wartości* typu | ||
`undefined`, przypisanie nowej wartości do tej zmiennej **nie** zmienia wartości | ||
*typu* `undefined`. | ||
|
||
Jednak, aby porównać coś do wartości `undefined` potrzebne jest odczytanie wartości | ||
`undefined`. | ||
|
||
Aby uchronić swój kod przeciwko możliwemu nadpisaniu zmiennej `undefined`, korzysta | ||
się z powszechnej techniki dodania dodatkowego parametru do | ||
[anonimowego wrappera](#function.scopes), do którego nie zostanie przekazany | ||
argument. | ||
|
||
var undefined = 123; | ||
(function(something, foo, undefined) { | ||
// undefined lokalnym zasięgu znowu | ||
// odnosi się do poprawnej wartości | ||
|
||
})('Hello World', 42); | ||
|
||
Kolejnym sposobem aby osiągnąć ten sam efekt jest użycie deklaracji zmiennej | ||
wewnątrz wrappera. | ||
|
||
var undefined = 123; | ||
(function(something, foo) { | ||
var undefined; | ||
... | ||
|
||
})('Hello World', 42); | ||
|
||
Jedyną różnicą pomięcy tymi sposobami są dodatkowe 4 bajty przeznaczone na słowo | ||
kluczowe `var` i spację po nim. | ||
|
||
### Zastosowanie `null` | ||
|
||
Podczas gdy `undefined` w kontekście języka jest używany jak *null* w sensie | ||
tradycyjnych języków, to `null` w JavaScript (jako literał i jako typ) jest po | ||
prostu kolejnym typem danych. | ||
|
||
Jest wykorzystywany we wnętrzu JavaScript (np. deklaracji końca łańcucha prototypów | ||
poprzez ustawienie `Foo.prototype = null`), ale prawie w każdym przypadku można go | ||
zastąpić przez `undefined`. | ||
|
Oops, something went wrong.