Skip to content

Commit 403b6f3

Browse files
author
Lukasz Kufel
committed
PL forgot to add some files.
1 parent 95f57a7 commit 403b6f3

File tree

2 files changed

+367
-0
lines changed

2 files changed

+367
-0
lines changed

doc/pl/function/constructors.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
## Konstruktory
2+
3+
Konstruktory w JavaScript również wyglądają inaczej niż innych języka. Każde
4+
wywołanie funkcji, które jest poprzedone słowem kluczowym `new` zachowuje się
5+
jak konstruktor.
6+
7+
Wewnątrz konstruktora - wywoływanej fukcji - wartość `this` wskazuje na
8+
nowo utworzony obiekt `Object`. Prototyp [`prototype`](#object.prototype) tego
9+
**nowego** obiektu będzie wskazywał na prototyp `prototype` obiektu fukcji,
10+
która została wywołana jako konstruktor.
11+
12+
Jeżeli wywołana funkcja nie posiada jawnej deklaracji `return`, wówczas
13+
fukcja domyślnie zwraca wartość `this` - nowy obiekt.
14+
15+
function Foo() {
16+
this.bla = 1;
17+
}
18+
19+
Foo.prototype.test = function() {
20+
console.log(this.bla);
21+
};
22+
23+
var test = new Foo();
24+
25+
Powyżej wywołanya została funkcja `Foo` jako konstruktor oraz ustawia
26+
nowo utworzonemu obiektowi właściwość `prototype` na `Foo.prototype`.
27+
28+
W tym przypadku jawna deklaracja `return` w funkcji zwraca wartość
29+
ustawioną w deklaracji, **ale tylko** jeżeli zwracaną wartością jest
30+
obiekt `Object`.
31+
32+
function Bar() {
33+
return 2;
34+
}
35+
new Bar(); // nowy obiekt
36+
37+
function Test() {
38+
this.value = 2;
39+
40+
return {
41+
foo: 1
42+
};
43+
}
44+
new Test(); // zwrócony obiekt
45+
46+
Jeżeli słowo kluczowe `new` zostanie pominięte funkcja **nie** zwróci nowego
47+
obiektu.
48+
49+
function Foo() {
50+
this.bla = 1; // zostanie ustawiona w obiekcie global
51+
}
52+
Foo(); // undefined
53+
54+
Mimo, że powyższy kod może zadziałać w pewnych przypadkach, w związku
55+
z działaniem [`this`](#function.this) w języku JavaScript to jako
56+
wartość `this`zostanie wykorzystany **obiekt global**.
57+
58+
### Fabryki
59+
60+
Aby móc ominąć słowo kluczowe `new` konstruktor musi jawnie zwracać wartość.
61+
62+
function Bar() {
63+
var value = 1;
64+
return {
65+
method: function() {
66+
return value;
67+
}
68+
}
69+
}
70+
Bar.prototype = {
71+
foo: function() {}
72+
};
73+
74+
new Bar();
75+
Bar();
76+
77+
Oba wywołania `Bar` zwrócą tą samą rzecz, nowo utworzony obiekt, który posiada
78+
właściwość nazwaną `method` w sobie, dla którego `Bar` jest [Domknięciem](#function.closures).
79+
80+
Należy również pamiętać, że wywołanie `new Bar()` **nie** ma wpływu na
81+
prototyp zwróconego obiektu (prototypem będzie `object.prototype` a nie `Bar.prototype`).
82+
Podczas gdy prototyp zostanie przypisany do nowo utworzonego obiektu, to jednak `Bar`
83+
nidgy nie zwróci tego nowego obiektu `Bar`, ale literał obiektu, który jest po
84+
słowie kluczowym `return`.
85+
86+
W powyższym przykładzie nie ma żadnej różnicy w działaniu pomiędzy użyciem
87+
i nieużyciem słowa kluczowego `new`.
88+
89+
### Tworzenie nowych obiektów używając fabryk
90+
91+
Często zaleca się **nie** korzystać z operatora `new` ponieważ zapominając
92+
go zastosować może prowadzić do błędów.
93+
94+
W celu stworzenia nowego obiektu, powinno się używać fabryki i konstruować
95+
nowy obiekt wewnątrz tej fabryki.
96+
97+
function Foo() {
98+
var obj = {};
99+
obj.value = 'blub';
100+
101+
var private = 2;
102+
obj.someMethod = function(value) {
103+
this.value = value;
104+
}
105+
106+
obj.getPrivate = function() {
107+
return private;
108+
}
109+
return obj;
110+
}
111+
112+
113+
Mimo, że powyższy kod jest odporny na brak słowa kluczowego `new` i ułatwia
114+
korzystanie ze [zmiennych prywatnych](#function.closures), to posiada
115+
pewne wady.
116+
While the above is robust against a missing `new` keyword and certainly makes
117+
the use of [private variables](#function.closures) easier, it comes with some
118+
downsides.
119+
1. Zużywa więcej pamięci, ponieważ tworzony obiekt **nie** współdzieli metod
120+
poprzez prototyp
121+
2. Aby móc dziedziczyć fabryka musi skopiować wszystkie metody z dziedziczonego
122+
obiektu lub przypisać ten obiekt, z którego się dziedziczy, jako prototyp
123+
do nowo utworzonego obiektu.
124+
3. Porzucenie łańcucha prototypów tylko ze względu na opuszczone słowo kluczowe
125+
`new` jest sprzeczne z duchem języka.
126+
127+
### Wnioski
128+
129+
Pominięcie słowa kluczowego `new` może prowadzić do błędów, ale na pewno nie
130+
powinno to być powodem odrzucenia używania prototypów w ogóle. Sprowadza się to
131+
do wyboru rozwiązania, które bardziej pasuje do potrzeb aplikacji. Szczególnie
132+
ważne jest aby wybrać określony styl tworzenia obiektów i się go **trzymać**.
133+

doc/pl/function/scopes.md

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
## Zasięg zmiennych i przestrzenie nazw
2+
3+
Mimo, że JavaScript radzi sobie dobrze ze składnią, opisującą dwa pasujące
4+
nawiasy klamrowe jako blok, to jednak **nie** wspiera zasięgu blokowego.
5+
Jedynym zasięgiem jaki istnieje w JavaScript jest *zasięg funkcyjny*.
6+
7+
function test() { // definiuje zasięg (scope)
8+
for(var i = 0; i < 10; i++) { // nie definiuje zasięgu (scope)
9+
// count
10+
}
11+
console.log(i); // 10
12+
}
13+
14+
> **Uwaga:** Jeżeli notacja `{...}` nie jest użyta w przypisaniu, deklaracji return
15+
> lub jako argument funkcji to zostanie zinterpretowana jako deklaracja bloku, a
16+
> **nie** jako literał obiektu. W połączeniu z [automatycznym wstawianiem średnika](#core.semicolon),
17+
> może prowadzić do subtelnych błędów.
18+
19+
W JavaScripcie nie ma również przestrzeni nazw, co oznacza, że wszystko jest
20+
definiowane w jednej *globalnie współdzielonej* przestrzeni nazw.
21+
22+
Za każdym razem gdy zmienna jest
23+
Z każdym odwołaniem do zmiennej JavaScript przeszukuje w górę wszystkie zasięgi
24+
dopóki nie znajdzie tej zmiennej. W przypadku gdy przeszukiwanie dotrze do globalnego
25+
zasięgu i nadal nie znajdzie żądanej nazwy to wyrzuca błąd `ReferenceError`.
26+
27+
### Zmora globalnych zmiennych
28+
29+
// script A
30+
foo = '42';
31+
32+
// script B
33+
var foo = '42'
34+
35+
Powyższe dwa skrypty **nie** dają tego samego efektu. Skrypt A definiuje zmienna
36+
nazwaną `foo` w *globalnym* zasięgu natomiast skrypt B definiuje `foo`
37+
w *aktualnym* zasięgu.
38+
39+
Jeszcze raz, to wcale nie daje *tego samego efektu*, nie użycie `var` może mieć
40+
poważne konsekwencje.
41+
42+
// globalny zasięg
43+
var foo = 42;
44+
function test() {
45+
// lokalny zasięg
46+
foo = 21;
47+
}
48+
test();
49+
foo; // 21
50+
51+
Pominięcie słowa `var` w deklaracji wewnątrz funkcji `test` nadpisze wartość
52+
zmiennej globalnej `foo`. Mimo, że nie wygląda to na początku jak duży problem,
53+
to posiadając wiele tysięcy linii kodu w JavaScript i nie korzystanie z `var`
54+
wprowadzi straszne i trudne do wyśledzenia błędy.
55+
56+
// globalny zasięg
57+
var items = [/* jakaś lista */];
58+
for(var i = 0; i < 10; i++) {
59+
subLoop();
60+
}
61+
62+
function subLoop() {
63+
// scope of subLoop
64+
for(i = 0; i < 10; i++) { // brakuje słowa var w deklaracji
65+
// do amazing stuff!
66+
}
67+
}
68+
69+
Zewnętrzna pętla zakończy działanie po pierwszym wywołaniu `subLoop`, ponieważ
70+
`subLoop` nadpisuje wartość globalnej zmiennej `i`. Użycie `var` w drugiej pętli
71+
`for` pozwoliło by łatwo uniknąć problemu. Słowo kluczowe `var` nie powinno być
72+
**nigdy** pominięte w deklaracji, chyba że *pożądanym skutkiem* jest wpłynięcie na
73+
zewnętrzny zasięg.
74+
75+
### Lokalne zmienne
76+
77+
Jedynym źródłem zmiennych lokalnych w JavaScripcie są parametry [funkcji](#function.general)
78+
oraz zmienne zadeklarowane poprzez deklaracje `var` wewnątrz funkcji.
79+
80+
// globalny zasięg
81+
var foo = 1;
82+
var bar = 2;
83+
var i = 2;
84+
85+
function test(i) {
86+
// lokalny zasięg fukcji test
87+
i = 5;
88+
89+
var foo = 3;
90+
bar = 4;
91+
}
92+
test(10);
93+
94+
Zmienne `foo` oraz `i` są lokalnymi zmiennymi wewnątrz zasiegu funkcji `test`,
95+
natomiast przypisanie wartości do `bar` nadpisze zmienną globalną o tej samej nazwie.
96+
97+
### "Hoisting" - wywindowanie, podnoszenie
98+
99+
JavaScript **winduje** deklaracje. Oznacza to, że zarówno deklaracja ze słowem
100+
kluczowym `var` jak i deklaracje funkcji `function` zostaną przeniesione na
101+
początek otaczającego zasięgu.
102+
103+
bar();
104+
var bar = function() {};
105+
var someValue = 42;
106+
107+
test();
108+
function test(data) {
109+
if (false) {
110+
goo = 1;
111+
112+
} else {
113+
var goo = 2;
114+
}
115+
for(var i = 0; i < 100; i++) {
116+
var e = data[i];
117+
}
118+
}
119+
120+
Powyższy kod zostanie przekształcony przed rozpoczęciem wykonania. JavaScript
121+
przeniesie deklarację zmiennej `var` oraz deklarację funkcji `function` na szczyt
122+
najbliższego zasięgu.
123+
124+
// deklaracje var zostaną przeniesione tutaj
125+
var bar, someValue; // ustawione domyślnie na 'undefined'
126+
127+
// deklaracje funkcji zostaną również przeniesione na górę
128+
function test(data) {
129+
var goo, i, e; // brak blokowego zasięgu spowoduje przeniesienie tutaj
130+
if (false) {
131+
goo = 1;
132+
133+
} else {
134+
goo = 2;
135+
}
136+
for(i = 0; i < 100; i++) {
137+
e = data[i];
138+
}
139+
}
140+
141+
bar(); // powoduje błąd TypeError ponieważ bar jest nadal 'undefined'
142+
someValue = 42; // przypisania nie zostają zmienione przez 'hoisting'
143+
bar = function() {};
144+
145+
test();
146+
147+
Brak blokowego zasięgu nie tylko przeniesie deklaracje `var` poza ciało pętle,
148+
ale również spowoduje, że niektóre porównania `if` staną się nieintuicyjne.
149+
150+
W oryginalnym kodzie wewnątrz deklaracja `if` zdaje się modyfikować *zmienną
151+
globalną* `goo`, podczas gdy faktycznie modyfikuje ona *zmienną lokalną* - po tym
152+
jak zostało zastosowane windowanie (hoisting).
153+
154+
Bez wiedzy na temat podnoszenia (hoistingu), poniższy kod może wydawać się
155+
wyrzucać błąd `ReferenceError`.
156+
157+
// sprawdz czy SomeImportantThing zostało zainicjalizowane
158+
if (!SomeImportantThing) {
159+
var SomeImportantThing = {};
160+
}
161+
162+
Oczywiście powyższy kod działa ze względu na fakt, że deklaracja `var` zostanie
163+
przeniesiona na początek *globalnego zasięgu*.
164+
165+
var SomeImportantThing;
166+
167+
// inny kod który może ale nie musi zainicjalizować SomeImportantThing
168+
169+
// upewnienie sie że SomeImportantThing zostało zainicjalizowane
170+
if (!SomeImportantThing) {
171+
SomeImportantThing = {};
172+
}
173+
174+
### Kolejność rozwiązywania nazw
175+
176+
Wszystkie zasięgi w JavaScripcie, włączając *globalny zasięg*, posiadają
177+
zdefiniowana wewnątrz specjalną nazwę [`this`](#function.this), która wskazuje
178+
na *aktualny obiekt*.
179+
180+
Zasięg funkcyjny posiada również zdefiniowaną wewnętrznie nazwę
181+
[`arguments`](#function.arguments), która zawiera listę argumentów przekazaną do
182+
funkcji.
183+
184+
Na przykład, kiedy próbujemy odczytać zmienną `foo` wewnątrz zasięgu funkcji,
185+
JavaScript będzie szukać nazwy w określonej kolejności:
186+
1. Jeżeli wewnątrz aktualnego zasięgu znajduje się deklaracja `var foo` skorzystaj z niej.
187+
2. Jeżeli jeden z parametrów fukcji został nazwany `foo` użyj go.
188+
3. Jeżeli fukcja została nazwana `foo` skorzystaj z tego.
189+
4. Przejdz do zewnętrznego zasięgu i przejdz do kroku **#1**.
190+
191+
> **Uwaga:** Jeżeli jeden z parametrów fukcji został nazwany `arguments` zapobiegnie
192+
> to utworzenia domyślnego obiektu `arguments`.
193+
194+
### Przestrzenie nazw
195+
196+
Powszechnym problemem posiadania tylko jednej globalnej przestrzeni nazw jest
197+
prawdopodobieństwo wystąpienia kolizji nazw. W JavaScripcie, można łatwo uniknąć
198+
tego problemu korzystając z *anonimowych wrapperów*.
199+
200+
(function() {
201+
// autonomiczna "przestrzeń nazw"
202+
203+
window.foo = function() {
204+
// wyeksponowane domkniecie (closure)
205+
};
206+
207+
})(); // natychmiastowe wykonanie funkcji
208+
209+
Nienazwane funkcje są rozpoznane jako [wyrażenia](#function.general), więc
210+
aby mogły zostać wywołane muszą zostać zewaluowane.
211+
212+
( // zewaluowanie fukcji znajdującej się wewnątrz nawiasów
213+
function() {}
214+
) // zwrócenie obiektu funkcji
215+
() // wywołanie rezultatu ewaluacji
216+
217+
Istnieją inne sposoby aby zewaluować i wykonać wyrażenie funkcyjne. Mimo, że
218+
mają inną składnie, zachowują się dokładnie tak samo.
219+
220+
// Trzy inne sposoby
221+
!function(){}();
222+
+function(){}();
223+
(function(){}());
224+
225+
### Wnioski
226+
227+
Zaleca się aby zawsze używać *anonimowych wrapperów* do hermetyzacji kodu wewnątrz
228+
jego własnej przestrzeni nazw. To nie tylko chroni kod przed kolizją nazw, ale
229+
również wprowadza lepszą modularyzację programów.
230+
231+
Ponadto, stosowanie zmiennych globalnych jest uznawane za złą praktykę.
232+
Jakiekolwiek wykorzystanie zmiennych globalnych wskazuje na źle napisany kod,
233+
który jest podatny na błędy i trudny do utrzymania.
234+

0 commit comments

Comments
 (0)