Efektywny JavaScript 68 sposobow wykorzystania potegi jezyka

background image
background image

Tytuł oryginału: Effective JavaScript: 68 Specific Ways to Harness the Power of JavaScript

Tłumaczenie: Tomasz Walczak

ISBN: 978-83-283-1418-4

Authorized translation from the English language edition, entitled: EFFECTIVE JAVASCRIPT: 68
SPECIFIC WAYS TO HARNESS THE POWER OF JAVASCRIPT; ISBN 0321812182; by David Herman;
published by Pearson Education, Inc, publishing as Addison Wesley.
Copyright © 2013 by Pearson Education, Inc.

All rights reserved. No part of this book may by reproduced or transmitted in any form or by any means,
electronic or mechanical, including photocopying, recording or by any information storage retrieval system,
without permission from Pearson Education, Inc.
Polish language edition published by HELION S.A. Copyright © 2015.

Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej
publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną,
fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym powoduje
naruszenie praw autorskich niniejszej publikacji.

Wszystkie znaki występujące w tekście są zastrzeżonymi znakami firmowymi bądź towarowymi ich
właścicieli.

Autor oraz Wydawnictwo HELION dołożyli wszelkich starań, by zawarte w tej książce informacje były
kompletne i rzetelne. Nie biorą jednak żadnej odpowiedzialności ani za ich wykorzystanie, ani za związane
z tym ewentualne naruszenie praw patentowych lub autorskich. Autor oraz Wydawnictwo HELION nie
ponoszą również żadnej odpowiedzialności za ewentualne szkody wynikłe z wykorzystania informacji
zawartych w książce.

Wydawnictwo HELION
ul. Kościuszki 1c, 44-100 GLIWICE
tel. 32 231 22 19, 32 230 98 63
e-mail:

helion@helion.pl

WWW:

http://helion.pl (księgarnia internetowa, katalog książek)

Pliki z przykładami omawianymi w książce można znaleźć pod adresem:
ftp://ftp.helion.pl/przyklady/efprjs.zip

Drogi Czytelniku!
Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres
http://helion.pl/user/opinie/efprjs
Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję.

Printed in Poland.

Kup książkę

Poleć książkę

Oceń książkę

Księgarnia internetowa

Lubię to! » Nasza społeczność

background image

Spis treĤci

Przedmowa .................................................................................... 11

Wprowadzenie ................................................................................ 13

Podzičkowania ............................................................................... 15

O autorze ....................................................................................... 17

Rozdziaã 1. Przyzwyczajanie sič do JavaScriptu ............................. 19

Sposób 1. Ustal, której wersji JavaScriptu uİywasz...................................... 19
Sposób 2. Liczby zmiennoprzecinkowe w JavaScripcie.................................. 24
Sposób 3. Uwaİaj na niejawnĈ konwersjč typu............................................. 27
Sposób 4. Stosuj typy proste zamiast nakãadek obiektowych ........................ 32
Sposób 5. Unikaj stosowania operatora == dla wartoĤci o róİnych typach .... 34
Sposób 6. Ograniczenia mechanizmu automatycznego

dodawania Ĥredników .................................................................. 37

Sposób 7. Traktuj ãaęcuchy znaków jak sekwencje

16-bitowych jednostek kodowych................................................. 43

Rozdziaã 2. Zasičg zmiennych ......................................................... 47

Sposób 8. Minimalizuj liczbč obiektów globalnych....................................... 47
Sposób 9. Zawsze deklaruj zmienne lokalne ................................................ 50
Sposób 10. Unikaj sãowa kluczowego with.................................................... 51
Sposób 11. Poznaj domkničcia ..................................................................... 54
Sposób 12. Niejawne przenoszenie deklaracji zmiennych

na poczĈtek bloku (czyli hoisting)............................................... 57

Sposób 13. Stosuj wyraİenia IIFE do tworzenia zasičgu lokalnego ................ 59

Poleć książkę

Kup książkę

background image

8

Spis treĤci

Sposób 14. Uwaİaj na nieprzenoĤne okreĤlanie zasičgu

nazwanych wyraİeę funkcyjnych............................................... 62

Sposób 15. Uwaİaj na nieprzenoĤne okreĤlanie zasičgu lokalnych

deklaracji funkcji w bloku ......................................................... 65

Sposób 16. Unikaj tworzenia zmiennych lokalnych

za pomocĈ funkcji eval .............................................................. 67

Sposób 17. Przedkãadaj poĤrednie wywoãania eval

nad bezpoĤrednie wywoãania tej funkcji ..................................... 68

Rozdziaã 3. Korzystanie z funkcji..................................................... 71

Sposób 18. Róİnice mičdzy wywoãaniami funkcji, metod i konstruktorów..... 71
Sposób 19. Funkcje wyİszego poziomu ........................................................ 74
Sposób 20. Stosuj instrukcjč call do wywoãywania metod

dla niestandardowego odbiorcy.................................................. 77

Sposób 21. Stosuj instrukcjč apply do wywoãywania funkcji

o róİnej liczbie argumentów....................................................... 79

Sposób 22. Stosuj sãowo kluczowe arguments do tworzenia funkcji

wariadycznych........................................................................... 81

Sposób 23. Nigdy nie modyfikuj obiektu arguments ..................................... 82
Sposób 24. Uİywaj zmiennych do zapisywania referencji

do obiektu arguments................................................................ 84

Sposób 25. Uİywaj instrukcji bind do pobierania metod o staãym odbiorcy... 85
Sposób 26. Uİywaj metody bind do wiĈzania funkcji

z podzbiorem argumentów (technika currying).............................. 87

Sposób 27. Wybieraj domkničcia zamiast ãaęcuchów znaków

do hermetyzowania kodu ........................................................... 88

Sposób 28. Unikaj stosowania metody toString funkcji ................................ 90
Sposób 29. Unikaj niestandardowych wãaĤciwoĤci przeznaczonych

do inspekcji stosu...................................................................... 92

Rozdziaã 4. Obiekty i prototypy ....................................................... 95

Sposób 30. Róİnice mičdzy instrukcjami prototype,

getPrototypeOf i __proto__.......................................................... 95

Sposób 31. Stosuj instrukcjč Object.getPrototypeOf zamiast __proto__ ......... 99
Sposób 32. Nigdy nie modyfikuj wãaĤciwoĤci __proto__ ............................... 100
Sposób 33. Uniezaleİnianie konstruktorów od instrukcji new .................... 101
Sposób 34. Umieszczaj metody w prototypach............................................ 103
Sposób 35. Stosuj domkničcia do przechowywania prywatnych danych ..... 105
Sposób 36. Stan egzemplarzy przechowuj tylko w nich samych .................. 107
Sposób 37. Zwracaj uwagč na niejawne wiĈzanie obiektu this .................... 109

Poleć książkę

Kup książkę

background image

Spis treĤci

9

Sposób 38. Wywoãywanie konstruktorów klasy bazowej

w konstruktorach klas pochodnych ......................................... 111

Sposób 39. Nigdy nie wykorzystuj ponownie nazw wãaĤciwoĤci

z klasy bazowej........................................................................ 115

Sposób 40. Unikaj dziedziczenia po klasach standardowych....................... 117
Sposób 41. Traktuj prototypy jak szczegóã implementacji ........................... 119
Sposób 42. Unikaj nieprzemyĤlanego stosowania techniki

monkey patching ..................................................................... 120

Rozdziaã 5. Tablice i sãowniki .........................................................123

Sposób 43. Budowanie prostych sãowników

na podstawie egzemplarzy typu Object..................................... 123

Sposób 44. Stosuj prototypy null, aby uniknĈþ zaĤmiecania

przez prototypy........................................................................ 126

Sposób 45. Uİywaj metody hasOwnProperty do zabezpieczania sič

przed zaĤmiecaniem przez prototypy

Sposób 46. Stosuj tablice zamiast sãowników

przy tworzeniu kolekcji uporzĈdkowanych ............................... 132

Sposób 47. Nigdy nie dodawaj enumerowanych wãaĤciwoĤci

do prototypu Object.prototype ................................................. 134

Sposób 48. Unikaj modyfikowania obiektu w trakcie enumeracji ................ 136
Sposób 49. Stosuj pčtlč for zamiast pčtli for…in

przy przechodzeniu po tablicy .................................................. 140

Sposób 50. Zamiast pčtli stosuj metody do obsãugi iteracji ......................... 142
Sposób 51. Wykorzystaj uniwersalne metody klasy Array

w obiektach podobnych do tablic ............................................. 146

Sposób 52. Przedkãadaj literaãy tablicowe nad konstruktor klasy Array ...... 148

Rozdziaã 6. Projekty bibliotek i interfejsów API ..............................151

Sposób 53. Przestrzegaj spójnych konwencji .............................................. 151
Sposób 54. Traktuj wartoĤþ undefined jak brak wartoĤci............................ 153
Sposób 55. Stosuj obiekty z opcjami do przekazywania argumentów

za pomocĈ sãów kluczowych..................................................... 157

Sposób 56. Unikaj niepotrzebnego przechowywania stanu ........................... 161
Sposób 57. OkreĤlaj typy na podstawie struktury,

aby tworzyþ elastyczne interfejsy.............................................. 164

Sposób 58. Róİnice mičdzy tablicami a obiektami podobnymi do tablic ...... 167
Sposób 59. Unikaj nadmiernej koercji ........................................................ 171
Sposób 60. Obsãuga ãaęcuchów metod ....................................................... 174

Poleć książkę

Kup książkę

background image

10

Spis treĤci

Rozdziaã 7. WspóãbieİnoĤþ ............................................................. 179

Sposób 61. Nie blokuj kolejki zdarzeę operacjami wejĤcia-wyjĤcia .............. 180
Sposób 62. Stosuj zagnieİdİone lub nazwane wywoãania zwrotne

do tworzenia sekwencji asynchronicznych wywoãaę ................. 183

Sposób 63. Pamičtaj o ignorowanych bãčdach ............................................ 187
Sposób 64. Stosuj rekurencjč do tworzenia asynchronicznych pčtli............ 190
Sposób 65. Nie blokuj kolejki zdarzeę obliczeniami .................................... 193
Sposób 66. Wykorzystaj licznik do wykonywania wspóãbieİnych operacji ... 197
Sposób 67. Nigdy nie uruchamiaj synchronicznie asynchronicznych

wywoãaę zwrotnych ................................................................. 201

Sposób 68. Stosuj obietnice, aby zwičkszyþ

przejrzystoĤþ asynchronicznego kodu ...................................... 203

Skorowidz .................................................................................... 207

Poleć książkę

Kup książkę

background image

Korzystanie z funkcji

Funkcje to „woãy robocze” JavaScriptu. SĈ dla programistów jednoczeĤnie
podstawowĈ abstrakcjĈ i mechanizmem implementacyjnym. Funkcje odgry-
wajĈ tu role, które w innych jčzykach sĈ przypisane do wielu róİnych elemen-
tów: procedur, metod, konstruktorów, a nawet klas i moduãów. Gdy zapoznasz
sič z subtelnymi aspektami funkcji, opanujesz istotnĈ czčĤþ JavaScriptu.
Pamičtaj jednak o tym, İe nauka efektywnego posãugiwania sič funkcjami
w róİnych kontekstach wymaga czasu.

Sposób 18. Róİnice mičdzy wywoãaniami funkcji, metod

i konstruktorów

JeĤli programowanie obiektowe nie jest Ci obce, prawdopodobnie traktujesz
funkcje, metody i konstruktory klas jako trzy odrčbne elementy. W Java-
Scripcie odpowiadajĈ im trzy róİne sposoby korzystania z jednej konstrukcji
— z funkcji.

Najprostszy sposób to wywoãanie funkcji:

function hello(username) {
return "Witaj, " + username;
}

hello("Keyser Söze"); // "Witaj, Keyser Söze"

Ten kod dziaãa w standardowy sposób — wywoãuje funkcjč

hello

i wiĈİe pa-

rametr

name

z podanym argumentem.

Metody w JavaScripcie to naleİĈce do obiektów wãaĤciwoĤci, które sĈ funk-
cjami:

var obj = {
hello: function() {
return "Witaj, " + this.username;
},

Poleć książkę

Kup książkę

background image

72

Rozdziaã 3. Korzystanie z funkcji

username: "Hans Gruber"

};

obj.hello(); // "Witaj, Hans Gruber"

Zauwaİ, İe w metodzie

hello

uİywane jest sãowo

this

, aby uzyskaþ dostčp

do obiektu

obj

. Moİe sič wydawaþ, İe

this

zostaje zwiĈzane z

obj

, poniewaİ

metodč

hello

zdefiniowano wãaĤnie w obiekcie

obj

. Jednak moİna skopiowaþ

referencjč do tej samej funkcji w innym obiekcie i uzyskaþ odmienny wynik:

var obj2 = {

hello: obj.hello,

username: "Boo Radley"

};

obj2.hello(); // "Witaj, Boo Radley"

W wywoãaniu metody samo wywoãanie okreĤla, z czym zwiĈzane jest sãowo

this

(wyznacza ono odbiorcč wywoãania). Wyraİenie

obj.hello()

powoduje

wyszukanie wãaĤciwoĤci

hello

obiektu

obj

i wywoãanie jej dla odbiorcy

obj

.

Wyraİenie

obj2.hello()

prowadzi do wyszukiwania wãaĤciwoĤci

hello

obiektu

obj2

; tĈ wãaĤciwoĤciĈ jest ta sama funkcja co w wywoãaniu

obj.hello

, tu jednak

jest ona wywoãywana dla odbiorcy

obj2

. Wywoãanie metody obiektu stan-

dardowo prowadzi do wyszukania metody i uİycia danego obiektu jako od-
biorcy tej metody.

Poniewaİ metody to funkcje wywoãane dla okreĤlonego obiektu, moİna swo-
bodnie wywoãywaþ zwykãe funkcje z wykorzystaniem sãowa kluczowego

this

:

function hello() {

return "Witaj, " + this.username;

}

Takie rozwiĈzanie moİe okazaþ sič przydatne, jeĤli chcesz wstčpnie zdefi-
niowaþ funkcjč, która bčdzie uİywana w wielu obiektach:

var obj1 = {

hello: hello,

username: "Gordon Gekko"

};

obj1.hello(); // "Witaj, Gordon Gekko"

var obj2 = {

hello: hello,

username: "Biff Tannen"

};

obj2.hello(); // "Witaj, Biff Tannen"

Jednak funkcja wykorzystujĈca sãowo kluczowe

this

nie jest przydatna, jeĤli

chcesz jĈ wywoãywaþ jak zwykãĈ funkcjč, a nie jak metodč:

hello(); // "Witaj, undefined"

Nie pomaga to, İe w zwykãych wywoãaniach funkcji (nie w metodach) odbior-
cĈ jest obiekt globalny, który tu nie ma wãaĤciwoĤci o nazwie

name

i zwraca

wartoĤþ

undefined

. Wywoãanie metody jako funkcji rzadko jest przydatne, jeĤli

Poleć książkę

Kup książkę

background image

Sposób 18. Róİnice mičdzy wywoãaniami funkcji, metod i konstruktorów

73

dana metoda wykorzystuje sãowo kluczowe

this

. PrzyczynĈ jest to, İe trudno

oczekiwaþ, iİ obiekt globalny bčdzie miaã te same wãaĤciwoĤci co obiekt, dla
którego napisano danĈ metodč. Uİywanie w tym kontekĤcie obiektu global-
nego jest na tyle problematycznym rozwiĈzaniem domyĤlnym, İe w trybie
strict w standardzie ES5

this

jest domyĤlnie wiĈzane z wartoĤciĈ

undefined

:

function hello() {
"use strict";
return "Witaj, " + this.username;

}
hello(); // Błąd: nie można znaleźć właściwości "username" obiektu undefined

To pomaga wykryþ przypadkowe wykorzystanie metod jako zwykãych funkcji.
Kod szybko przestanie wtedy dziaãaþ, poniewaİ próba dostčpu do wãaĤciwoĤci
obiektu

undefined

spowoduje natychmiastowe zgãoszenie bãčdu.

Trzecim sposobem uİywania funkcji jest ich wywoãywanie jako konstrukto-
rów. Konstruktory, podobnie jak metody i zwykãe funkcje, definiuje sič za
pomocĈ sãowa kluczowego

function

:

function User(name, passwordHash) {
this.name = name;
this.passwordHash = passwordHash;
}

JeĤli wywoãasz funkcjč

User

z operatorem

new

, zostanie ona potraktowana jak

konstruktor:

var u = new User("sfalken",
"0ef33ae791068ec64b502d6cb0191387");
u.name; // "sfalken"

Wywoãanie konstruktora, w odróİnieniu od wywoãaę funkcji i metod, powo-
duje przekazanie nowego obiektu jako wartoĤci

this

i niejawne zwrócenie no-

wego obiektu jako wyniku. Gãównym zadaniem konstruktora jest inicjowanie
obiektów.

Co warto zapamičtaþ?

Q

W wywoãaniach metod naleİy podaþ obiekt (odbiorcč), w którym szukana
bčdzie wãaĤciwoĤþ w postaci tej metody.

Q

W wywoãaniach funkcji odbiorcĈ jest obiekt globalny (w trybie strict jest to
wartoĤþ

undefined

). Wywoãywanie metod jak zwykãych funkcji rzadko jest

przydatne.

Q

Konstruktory sĈ wywoãywane za pomocĈ sãowa kluczowego

new

, a ich od-

biorcĈ sĈ nowe obiekty.

Poleć książkę

Kup książkę

background image

74

Rozdziaã 3. Korzystanie z funkcji

Sposób 19. Funkcje wyİszego poziomu

Funkcje wyİszego poziomu byãy w przeszãoĤci znakiem rozpoznawczym
mistrzów programowania funkcyjnego. Te tajemnicze nazwy sugerujĈ, İe ma-
my tu do czynienia z zaawansowanĈ technikĈ programistycznĈ. Nic bardziej
mylnego. Wykorzystanie zwičzãej elegancji funkcji czčsto prowadzi do powsta-
nia prostszego i krótszego kodu. Przez lata w jčzykach skryptowych wprowa-
dzano techniki z tego obszaru. Dzički temu udaão sič przybliİyþ uİytkownikom
niektóre z najlepszych idiomów z dziedziny programowania funkcyjnego.

Funkcje wyİszego poziomu to po prostu funkcje, które przyjmujĈ inne funkcje
jako argumenty lub zwracajĈ inne funkcje jako wynik. Zwãaszcza przyjmo-
wanie argumentu w postaci funkcji (nazywanej czčsto funkcjĈ wywoãywanĈ
zwrotnie
, poniewaİ jest wywoãywana przez funkcjč wyİszego poziomu) to
wyjĈtkowo przydatny i zwičzãy idiom, czčsto wykorzystywany w programach
w JavaScripcie.

Przyjrzyj sič standardowej metodzie

sort

tablic. Aby mogãa ona dziaãaþ dla

wszystkich moİliwych tablic, wymaga od programu wywoãujĈcego okreĤlenia,
jak naleİy porównywaþ dwa elementy tablicy:

function compareNumbers(x, y) {

if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
}
[3, 1, 4, 1, 5, 9].sort(compareNumbers); // [1, 1, 3, 4, 5, 9]

W bibliotece standardowej moİna byão zaİĈdaþ, aby program wywoãujĈcy
przekazywaã obiekt z metodĈ

compare

, jednak poniewaİ wymagana jest tylko

jedna metoda, bezpoĤrednie przyjmowanie funkcji to prostsze i bardziej zwič-
zãe rozwiĈzanie. Przedstawiony wczeĤniej przykãad moİna uproĤciþ jeszcze
bardziej, stosujĈc funkcjč anonimowĈ:

[3, 1, 4, 1, 5, 9].sort(function(x, y) {
if (x < y) {
return -1;

}
if (x > y) {
return 1;
}
return 0;
}); // [1, 1, 3, 4, 5, 9]

Opanowanie funkcji wyİszego poziomu czčsto pozwala uproĤciþ kod i wyeli-
minowaþ nudny, szablonowy kod. Dla wielu typowych operacji na tablicach
istniejĈ Ĥwietne abstrakcje wyİszego rzčdu, z którymi warto sič zapoznaþ.

Poleć książkę

Kup książkę

background image

Sposób 19. Funkcje wyİszego poziomu

75

Przyjrzyj sič prostemu zadaniu przeksztaãcania tablicy ãaęcuchów znaków.
Za pomocĈ pčtli moİna napisaþ nastčpujĈcy kod:

var names = ["Fred", "Wilma", "Pebbles"];
var upper = [];
for (var i = 0, n = names.length; i < n; i++) {
upper[i] = names[i].toUpperCase();
}

upper; // ["FRED", "WILMA", "PEBBLES"]

Dzički wygodnej metodzie

map

tablic (wprowadzonej w standardzie ES5)

moİna caãkowicie zrezygnowaþ z pčtli i zaimplementowaþ transformacjč ko-
lejnych elementów za pomocĈ funkcji lokalnej:

var names = ["Fred", "Wilma", "Pebbles"];
var upper = names.map(function(name) {
return name.toUpperCase();
});

upper; // ["FRED", "WILMA", "PEBBLES"]

Gdy przyzwyczaisz sič do korzystania z funkcji wyİszego poziomu, zaczniesz
dostrzegaþ okazje do ich samodzielnego pisania. DobrĈ oznakĈ wskazujĈcĈ,
İe taka funkcja moİe okazaþ sič przydatna, jest wystčpowanie powtarzajĈce-
go sič lub podobnego kodu. Zaãóİmy, İe jedna czčĤþ programu tworzy ãaę-
cuch znaków skãadajĈcy sič z liter alfabetu:

var aIndex = "a".charCodeAt(0); // 97

var alphabet = "";
for (var i = 0; i < 26; i++) {
alphabet += String.fromCharCode(aIndex + i);
}

alphabet; // "abcdefghijklmnopqrstuvwxyz"

Inna czčĤþ programu generuje ãaęcuch znaków obejmujĈcy cyfry:

var digits = "";
for (var i = 0; i < 10; i++) {
digits += i;
}
digits; // "0123456789"

W jeszcze innym fragmencie program tworzy ãaęcuch z losowych znaków:

var random = "";

for (var i = 0; i < 8; i++) {
random += String.fromCharCode(Math.floor(Math.random() * 26)
+ aIndex);
}

random; // "bdwvfrtp" (za każdym razem wynik jest inny)

Kaİdy fragment generuje inny ãaęcuch znaków, jednak logika dziaãania jest za
kaİdym razem podobna. Kaİda z pokazanych pčtli generuje ãaęcuch zna-
ków na podstawie scalania wyników obliczeę dajĈcych poszczególne znaki.

Poleć książkę

Kup książkę

background image

76

Rozdziaã 3. Korzystanie z funkcji

Moİna wyodrčbniþ wspólne aspekty i umieĤciþ je w jednej funkcji narzč-
dziowej:

function buildString(n, callback) {
var result = "";
for (var i = 0; i < n; i++) {
result += callback(i);
}
return result;
}

Zauwaİ, İe w funkcji

buildString

znajdujĈ sič wszystkie wspólne elementy

kaİdej pčtli, natomiast dla zmiennych aspektów stosowane sĈ parametry.
Liczbie iteracji pčtli odpowiada zmienna

n

, a do tworzenia kaİdego fragmentu

ãaęcucha sãuİy funkcja

callback

. Teraz moİna uproĤciþ kaİdy z trzech

przykãadów i zastosowaþ w nich funkcjč

buildString

:

var alphabet = buildString(26, function(i) {
return String.fromCharCode(aIndex + i);
});

alphabet; // "abcdefghijklmnopqrstuvwxyz"

var digits = buildString(10, function(i) { return i; });
digits; // "0123456789"

var random = buildString(8, function() {
return String.fromCharCode(Math.floor(Math.random() * 26)
+ aIndex);
});
random; // "ltvisfjr" (wynik za każdym razem jest inny)

Tworzenie abstrakcji wyİszego poziomu przynosi wiele korzyĤci. JeĤli w im-
plementacji wystčpujĈ skomplikowane fragmenty (trzeba na przykãad wãaĤci-
wie obsãuİyþ warunki graniczne dla pčtli), znajdujĈ sič one w funkcji wyİ-
szego poziomu. Dzički temu wystarczy naprawiþ bãčdy w logice raz, zamiast
szukaþ wszystkich wystĈpieę danego wzorca rozrzuconych po programie.
Takİe jeĤli stwierdzisz, İe trzeba zoptymalizowaþ wydajnoĤþ operacji, wystar-
czy to zrobiþ w jednym miejscu. Ponadto nadanie abstrakcji jednoznacznej
nazwy (takiej jak

buildString

, czyli „twórz ãaęcuch znaków”) jasno informuje

czytelników kodu o jego dziaãaniu. Dzički temu nie trzeba analizowaþ szcze-
góãów implementacji.

Stosowanie funkcji wyİszego poziomu po dostrzeİeniu, İe w kodzie powtarza sič
ten sam wzorzec, prowadzi do powstawania bardziej zwičzãego kodu, zwičk-
szenia produktywnoĤci i poprawy czytelnoĤci kodu. Zwracanie uwagi na po-
wtarzajĈce sič wzorce i przenoszenie ich do funkcji narzčdziowych wyİszego
poziomu to waİny nawyk, który warto sobie rozwinĈþ.

Poleć książkę

Kup książkę

background image

Sposób 20. Instrukcja call do wywoãywania metod dla niestandardowego odbiorcy

77

Co warto zapamičtaþ?

Q

Funkcje wyİszego poziomu charakteryzujĈ sič tym, İe przyjmujĈ inne
funkcje jako argumenty lub zwracajĈ funkcje jako wyniki.

Q

Zapoznaj sič z funkcjami wyİszego poziomu z istniejĈcych bibliotek.

Q

Naucz sič wykrywaþ powtarzajĈce sič wzorce, które moİna zastĈpiþ funk-
cjami wyİszego poziomu.

Sposób 20. Instrukcja call do wywoãywania metod dla niestandardowego odbiorcy

Sposób 20. Stosuj instrukcjč call do wywoãywania metod

dla niestandardowego odbiorcy

Odbiorca funkcji lub metody (czyli wartoĤþ wiĈzana ze specjalnym sãowem
kluczowym

this

) standardowo jest okreĤlany na podstawie skãadni wywoãa-

nia. Wywoãanie metody powoduje zwiĈzanie ze sãowem kluczowym

this

obiektu, w którym dana metoda jest wyszukiwana. Czasem jednak trzeba
wywoãaþ funkcjč dla niestandardowego odbiorcy, a nie jest ona jego wãaĤciwo-
ĤciĈ. Moİna oczywiĤcie dodaþ potrzebnĈ metodč jako nowĈ wãaĤciwoĤþ danego
obiektu:

obj.temporary = f; // Co się stanie, jeśli właściwość obj.temporary już istniała?
var result = obj.temporary(arg1, arg2, arg3);

delete obj.temporary; // Co się stanie, jeśli właściwość obj.temporary już istniała?

Jednak to podejĤcie jest niewygodne, a nawet niebezpieczne. Czčsto nie nale-
İy, a nawet nie da sič zmodyfikowaþ obiektu takiego jak

obj

w przykãadzie.

Niezaleİnie od nazwy wybranej dla wãaĤciwoĤci (tu jest to

temporary

) istnieje

ryzyko kolizji z istniejĈcĈ wãaĤciwoĤciĈ obiektu. Ponadto niektóre obiekty
sĈ zamroİone lub zamkničte, co uniemoİliwia dodawanie do nich nowych
wãaĤciwoĤci. Ponadto dodawanie dowolnych wãaĤciwoĤci do obiektów to zãa
praktyka — zwãaszcza gdy sĈ to obiekty utworzone przez innego programistč
(zobacz Sposób 42.).

Na szczčĤcie funkcje majĈ wbudowanĈ metodč

call

, umoİliwiajĈcĈ podanie

niestandardowego odbiorcy. Wywoãanie funkcji za pomocĈ metody

call

:

f.call(obj, arg1, arg2, arg3);

dziaãa podobnie jak wywoãanie bezpoĤrednie:

f(arg1, arg2, arg3);

Róİnica polega na tym, İe w metodzie

call

pierwszy argument to jawnie

wskazany obiekt odbiorcy.

Metoda

call

jest wygodna przy wywoãywaniu metod, które mogãy zostaþ usu-

ničte, zmodyfikowane lub zastĈpione. W sposobie 45. przedstawiony jest przy-
datny przykãad, ilustrujĈcy wywoãywanie metody

hasOwnProperty

dla dowolnych

Poleć książkę

Kup książkę

background image

78

Rozdziaã 3. Korzystanie z funkcji

obiektów (nawet dla sãownika). W sãowniku sprawdzenie wãaĤciwoĤci

hasOw-

nProperty

powoduje zwrócenie wartoĤci ze sãownika, zamiast wywoãania

odziedziczonej metody:

dict.hasOwnProperty = 1;
dict.hasOwnProperty("foo"); // Błąd: 1 nie jest funkcją

Za pomocĈ metody

call

moİna wywoãaþ metodč

hasOwnProperty

dla sãownika,

nawet jeĤli nie jest ona zapisana w samym obiekcie:

var hasOwnProperty = {}.hasOwnProperty;
dict.foo = 1;
delete dict.hasOwnProperty;
hasOwnProperty.call(dict, "foo"); // true
hasOwnProperty.call(dict, "hasOwnProperty"); // false

Metoda

call

jest przydatna takİe przy definiowaniu funkcji wyİszego poziomu.

Czčsto stosowany idiom dotyczĈcy funkcji wyİszego poziomu polega na przyj-
mowaniu opcjonalnych argumentów okreĤlajĈcych odbiorcč, dla którego
funkcja ma zostaþ wywoãana. Na przykãad obiekt reprezentujĈcy tablicč
z parami klucz – wartoĤþ moİe udostčpniaþ metodč

forEach

:

var table = {
entries: [],
addEntry: function(key, value) {
this.entries.push({ key: key, value: value });
},
forEach: function(f, thisArg) {
var entries = this.entries;
for (var i = 0, n = entries.length; i < n; i++) {
var entry = entries[i];
f.call(thisArg, entry.key, entry.value, i);
}
}

};

To umoİliwia uİytkownikom obiektu podanie potrzebnej metody jako wy-
woãywanej zwrotnie funkcji

f

z metody

table.forEach

i wskazanie odpowied-

niego odbiorcy. Dzički temu moİna na przykãad wygodnie skopiowaþ za-
wartoĤþ jednej tablicy do drugiej:

table1.forEach(table2.addEntry, table2);

Ten kod uİywa metody

addEntry

obiektu

table2

(moİna teİ pobraþ tč metodč

z obiektu

Table.prototype

lub

table1

), a metoda

forEach

wielokrotnie wywoãuje

metodč

addEntry

dla odbiorcy

table2

. Zauwaİ, İe choþ metoda

addEntry

oczekuje

tylko dwóch argumentów, metoda

forEach

wywoãuje jĈ z trzema argumentami:

kluczem, wartoĤciĈ i indeksem. Dodatkowy argument w postaci indeksu
nie powoduje problemów, poniewaİ metoda

addEntry

po prostu go pomija.

Poleć książkę

Kup książkę

background image

Sposób 21. Instrukcja apply do wywoãywania funkcji o róİnej liczbie argumentów

79

Co warto zapamičtaþ?

Q

Uİywaj metody

call

do wywoãywania funkcji dla niestandardowych od-

biorców.

Q

Stosuj metodč

call

do wywoãywania metod, które mogĈ nie istnieþ w danym

obiekcie.

Q

Uİywaj metody

call

do definiowania funkcji wyİszego poziomu, umoİli-

wiajĈcych klientom okreĤlanie odbiorcy wywoãywanych zwrotnie funkcji.

Sposób 21. Instrukcja apply do wywoãywania funkcji o róİnej liczbie argumentów

Sposób 21. Stosuj instrukcjč apply do wywoãywania funkcji

o róİnej liczbie argumentów

WyobraĮ sobie, İe dostčpna jest funkcja obliczajĈca ĤredniĈ z dowolnej
liczby wartoĤci:

average(1, 2, 3); // 2
average(1); // 1
average(3, 1, 4, 1, 5, 9, 2, 6, 5); // 4
average(2, 7, 1, 8, 2, 8, 1, 8); // 4.625

Funkcja

average

jest funkcjĈ wariadycznĈ (ang. variadic), inaczej funkcjĈ

o zmiennej arnoĤci (arnoĤþ funkcji to liczba oczekiwanych przez niĈ argu-
mentów). Oznacza to tyle, İe moİe przyjmowaþ dowolnĈ liczbč argumentów.
Wersja funkcji

average

majĈca staãĈ arnoĤþ prawdopodobnie pobieraãaby je-

den argument z tablicĈ wartoĤci:

averageOfArray([1, 2, 3]); // 2
averageOfArray([1]); // 1
averageOfArray([3, 1, 4, 1, 5, 9, 2, 6, 5]); // 4
averageOfArray([2, 7, 1, 8, 2, 8, 1, 8]); // 4.625

Wersja wariadyczna jest bardziej zwičzãa i (choþ to kwestia dyskusyjna) bar-
dziej elegancka. Funkcje wariadyczne majĈ wygodnĈ skãadnič — przynajm-
niej wtedy, gdy uİytkownik od razu wie, ile argumentów chce podaþ. Tak
dzieje sič w przedstawionych przykãadach. WyobraĮ sobie jednak, İe tablica
wartoĤci jest tworzona w nastčpujĈcy sposób:

var scores = getAllScores();

Jak uİyþ funkcji

average

do obliczenia Ĥredniej z tych wartoĤci?

average(/* ? */);

Na szczčĤcie funkcje majĈ wbudowanĈ metodč

apply

. Dziaãa ona podobnie jak

metoda

call

, ale jest zaprojektowana w okreĤlonym celu. Metoda

apply

przyj-

muje tablicč argumentów i wywoãuje danĈ funkcjč w taki sposób, jakby kaİdy
element tablicy byã odrčbnym argumentem wywoãania tej funkcji. Oprócz

Poleć książkę

Kup książkę

background image

80

Rozdziaã 3. Korzystanie z funkcji

tablicy argumentów metoda

apply

przyjmuje dodatkowo pierwszy argument,

okreĤlajĈcy obiekt

this

dla wywoãywanej funkcji. Poniewaİ funkcja

average

nie uİywa obiektu

this

, wystarczy podaþ wartoĤþ

null

:

var scores = getAllScores();
average.apply(null, scores);

JeĤli tablica

scores

bčdzie miaãa na przykãad trzy elementy, przedstawiony

kod zadziaãa tak samo jak poniİsza wersja:

average(scores[0], scores[1], scores[2]);

Metoda

apply

dziaãa takİe dla metod wariadycznych. Na przykãad obiekt

buffer

moİe mieþ wariadycznĈ metodč

append

, przeznaczonĈ do dodawania elemen-

tów do jego wewnčtrznego stanu (aby zrozumieþ implementacjč tej metody

append

, zapoznaj sič ze Sposobem 22.):

var buffer = {
state: [],
append: function() {
for (var i = 0, n = arguments.length; i < n; i++) {
this.state.push(arguments[i]);
}
}
};

Metodč

append

moİna wywoãaþ z dowolnĈ liczbĈ argumentów:

buffer.append("Witaj, ");
buffer.append(firstName, " ", lastName, "!");
buffer.append(newline);

Za pomocĈ argumentu metody

apply

okreĤlajĈcego obiekt

this

moİna teİ

wywoãaþ tč metodč z generowanĈ tablicĈ:

buffer.append.apply(buffer, getInputStrings());

Zwróþ uwagč na znaczenie argumentu

buffer

. JeĤli przekaİesz niewãaĤciwy

obiekt, metoda

append

spróbuje zmodyfikowaþ wãaĤciwoĤþ

state

nieodpowied-

niego obiektu.

Co warto zapamičtaþ?

Q

Stosuj metodč

apply

do wywoãywania funkcji wariadycznych z generowa-

nymi tablicami argumentów.

Q

Za pomocĈ pierwszego argumentu metody

apply

moİesz wskazaþ odbiorcč

metod wariadycznych.

Poleć książkę

Kup książkę

background image

Sposób 22. Stosuj sãowo kluczowe arguments do tworzenia funkcji wariadycznych

81

Sposób 22. Stosuj sãowo kluczowe arguments

do tworzenia funkcji wariadycznych

W sposobie 21. znajduje sič opis funkcji wariadycznej

average

. Potrafi ona zwró-

ciþ ĤredniĈ z dowolnej liczby argumentów. Jak samodzielnie zaimplemen-
towaþ funkcjč wariadycznĈ? Napisanie funkcji

averageOfArray

o staãej arnoĤci

jest stosunkowo ãatwe:

function averageOfArray(a) {
for (var i = 0, sum = 0, n = a.length; i < n; i++) {
sum += a[i];
}
return sum / n;
}

averageOfArray([2, 7, 1, 8, 2, 8, 1, 8]); // 4.625

W tej definicji funkcji

averageOfArray

uİywany jest jeden parametr formalny

— zmienna

a

z listy parametrów. Gdy uİytkownicy wywoãujĈ funkcjč

averageOf

´

Array

, podajĈ pojedynczy argument (nazywany tak w celu odróİnienia od

parametru formalnego). Jest nim tablica wartoĤci.

Wersja wariadyczna wyglĈda niemal tak samo, ale nie sĈ w niej jawnie zdefi-
niowane İadne parametry formalne. Zamiast tego wykorzystywany jest fakt,
İe JavaScript dodaje do kaİdej funkcji niejawnĈ zmiennĈ lokalnĈ o nazwie

arguments

. Obiekt

arguments

umoİliwia dostčp do argumentów w sposób przypo-

minajĈcy uİywanie tablicy. Kaİdy argument ma okreĤlony indeks, a wãaĤci-
woĤþ

length

okreĤla, ile argumentów zostaão podanych. To sprawia, İe w funkcji

average

o zmiennej arnoĤci moİna przejĤþ w pčtli po wszystkich elementach

z obiektu

arguments

:

function average() {
for (var i = 0, sum = 0, n = arguments.length;
i < n;
i++) {
sum += arguments[i];
}

return sum / n;
}

Funkcje wariadyczne dajĈ duİo swobody. W róİnych miejscach moİna je wy-
woãywaþ z wykorzystaniem odmiennej liczby argumentów. Jednak same
w sobie majĈ pewne ograniczenia, poniewaİ gdy uİytkownicy chcĈ je wywo-
ãaþ dla generowanej tablicy argumentów, muszĈ zastosowaþ opisanĈ w spo-
sobie 21. metodč

apply

. Gdy w celu uãatwienia pracy udostčpniasz funkcjč

o zmiennej arnoĤci, to zgodnie z ogólnĈ reguãĈ powinieneĤ teİ utworzyþ wersjč
o staãej arnoĤci, przyjmujĈcĈ jawnie podanĈ tablicč. Zwykle jest to ãatwe, po-
niewaİ przewaİnie moİna zaimplementowaþ funkcjč wariadycznĈ jako prostĈ
nakãadkč przekazujĈcĈ zadania do wersji o staãej arnoĤci:

Poleć książkę

Kup książkę

background image

82

Rozdziaã 3. Korzystanie z funkcji

function average() {
return averageOfArray(arguments);
}

Dzički temu uİytkownicy funkcji nie muszĈ uciekaþ sič do stosowania meto-
dy

apply

, która moİe zmniejszaþ czytelnoĤþ kodu i czčsto prowadzi do spadku

wydajnoĤci.

Co warto zapamičtaþ?

Q

Stosuj niejawny obiekt

arguments

do implementowania funkcji o zmiennej

arnoĤci.

Q

PomyĤl o udostčpnieniu obok funkcji wariadycznych dodatkowych wersji
o staãej arnoĤci, aby uİytkownicy nie musieli stosowaþ metody

apply

.

Sposób 23. Nigdy nie modyfikuj obiektu arguments

Obiekt

arguments

wprawdzie wyglĈda jak tablica, ale niestety nie zawsze dziaãa

w ten sposób. ProgramiĤci znajĈcy Perla i uniksowe skrypty powãoki sĈ
przyzwyczajeni do stosowania techniki przesuwania elementów w kierunku
poczĈtku tablicy argumentów. Tablice w JavaScripcie udostčpniajĈ metodč

shift

, która usuwa pierwszy element tablicy i przesuwa wszystkie kolejne

elementy o jednĈ pozycjč. Jednak obiekt

arguments

nie jest egzemplarzem

standardowego typu

Array

, dlatego nie moİna bezpoĤrednio wywoãaþ metody

arguments.shift()

.

Moİe sič wydawaþ, İe dzički metodzie

call

da sič pobraþ metodč

shift

tablic

i wywoãaþ jĈ dla obiektu

arguments

. Na pozór jest to sensowny sposób imple-

mentacji funkcji takiej jak

callMethod

, która przyjmuje obiekt i nazwč metody

oraz próbuje wywoãaþ wskazanĈ metodč tego obiektu dla wszystkich pozo-
staãych argumentów:

function callMethod(obj, method) {
var shift = [].shift;
shift.call(arguments);
shift.call(arguments);
return obj[method].apply(obj, arguments);
}

Jednak dziaãanie tej funkcji jest dalekie od oczekiwanego:

var obj = {
add: function(x, y) { return x + y; }
};
callMethod(obj, "add", 17, 25);
// Błąd: nie można wczytać właściwości "apply" obiektu undefined

Poleć książkę

Kup książkę

background image

Sposób 23. Nigdy nie modyfikuj obiektu arguments

83

PrzyczynĈ problemów z tym kodem jest to, İe obiekt

arguments

nie jest kopiĈ

argumentów funkcji. Wszystkie nazwane argumenty to aliasy odpowiednich
indeksów z obiektu

arguments

. Tak wičc

obj

to alias dla

arguments[0]

, a

method

to alias dla

arguments[1]

. Jest tak nawet po usuničciu elementów z obiektu

arguments

za pomocĈ wywoãania

shift

. To oznacza, İe choþ na pozór uİywane

jest wywoãanie

obj["add"]

, w rzeczywistoĤci wywoãanie to

17[25]

. Na tym etapie

zaczynajĈ sič kãopoty. Z powodu obowiĈzujĈcej w JavaScripcie automatycz-
nej konwersji typów wartoĤþ

17

jest przeksztaãcana w obiekt typu

Number

, po

czym pobierana jest jego (nieistniejĈca) wãaĤciwoĤþ

"25"

, dlatego zwrócona

zostaje wartoĤþ

undefined

. Potem nastčpuje nieudana próba pobrania wãa-

ĤciwoĤci

"apply"

obiektu

undefined

w celu wywoãania jej jako metody.

Wniosek z tego jest taki, İe relacja mičdzy obiektem

arguments

a nazwanymi pa-

rametrami funkcji ãatwo staje sič Įródãem problemów. Modyfikacja obiektu

arguments

grozi przeksztaãceniem nazwanych parametrów funkcji w bezsen-

sowne dane. W trybie strict ze standardu ES5 komplikacje sĈ jeszcze wičksze.
Parametry funkcji w tym trybie nie sĈ aliasami elementów obiektu

arguments

.

Aby zademonstrowaþ róİnicč, moİna napisaþ funkcjč aktualizujĈcĈ element
z obiektu

arguments

:

function strict(x) {

"use strict";

arguments[0] = "zmodyfikowany";

return x === arguments[0];

}

function nonstrict(x) {

arguments[0] = "zmodyfikowany";

return x === arguments[0];

}

strict("niezmodyfikowany"); // false
nonstrict("niezmodyfikowany"); // true

Dlatego duİo bezpieczniej jest nigdy nie modyfikowaþ obiektu

arguments

. Moİ-

na ãatwo uzyskaþ ten efekt, kopiujĈc najpierw elementy z tego obiektu do
zwykãej tablicy. Oto prosty idiom ilustrujĈcy takĈ modyfikacjč:

var args = [].slice.call(arguments);

Metoda

slice

tablic tworzy kopič tablicy, gdy zostanie wywoãana bez dodatko-

wych argumentów. Zwracany wynik to egzemplarz standardowego typu

Array

.

Ten egzemplarz nie jest aliasem İadnych obiektów i umoİliwia bezpoĤredni
dostčp do wszystkich metod typu

Array

.

Aby naprawiþ implementacjč metody

callMethod

, naleİy skopiowaþ zawartoĤþ

obiektu

arguments

. Poniewaİ potrzebne sĈ tylko elementy po

obj

i

method

, do

metody

slice

moİna przekazaþ poczĈtkowy indeks równy

2

:

function callMethod(obj, method) {

var args = [].slice.call(arguments, 2);

return obj[method].apply(obj, args);

}

Poleć książkę

Kup książkę

background image

84

Rozdziaã 3. Korzystanie z funkcji

Teraz metoda

callMethod

dziaãa zgodnie z oczekiwaniami:

var obj = {
add: function(x, y) { return x + y; }
};

callMethod(obj, "add", 17, 25); // 42

Co warto zapamičtaþ?

Q

Nigdy nie modyfikuj obiektu

arguments

.

Q

JeĤli chcesz zmodyfikowaþ zawartoĤþ obiektu

arguments

, najpierw skopiuj

jĈ do zwykãej tablicy za pomocĈ instrukcji

[].slice.call(arguments)

.

Sposób 24. Uİywaj zmiennych do zapisywania referencji

do obiektu arguments

Iterator to obiekt, który zapewnia sekwencyjny dostčp do kolekcji danych.
Typowy interfejs API udostčpnia metodč

next

, która zwraca nastčpnĈ wartoĤþ

z sekwencji. Zaãóİmy, İe chcesz napisaþ uãatwiajĈcĈ pracč funkcjč, która
przyjmuje dowolnĈ liczbč argumentów i tworzy iterator do poruszania sič po
tych wartoĤciach:

var it = values(1, 4, 1, 4, 2, 1, 3, 5, 6);

it.next(); // 1
it.next(); // 4
it.next(); // 1

Funkcja

values

musi przyjmowaþ dowolnĈ liczbč argumentów, dlatego obiekt

iteratora naleİy utworzyþ tak, aby przechodziã po elementach obiektu

arguments

:

function values() {
var i = 0, n = arguments.length;
return {
hasNext: function() {
return i < n;
},
next: function() {
if (i >= n) {
throw newError("Koniec iteracji");
}
return arguments[i++]; // Nieprawidłowe argumenty
}
};
}

Jednak ten kod jest nieprawidãowy. Staje sič to oczywiste przy próbie uİycia
iteratora:

var it = values(1, 4, 1, 4, 2, 1, 3, 5, 6);

it.next(); // undefined

Poleć książkę

Kup książkę

background image

Sposób 25. Instrukcja bind do pobierania metod o staãym odbiorcy

85

it.next(); // undefined
it.next(); // undefined

Problem wynika z tego, İe nowa zmienna

arguments

jest niejawnie wiĈzana

w ciele kaİdej funkcji. Obiekt, który jest tu potrzebny, jest zwiĈzany z funk-
cjĈ

values

. Ale metoda

next

iteratora zawiera wãasnĈ zmiennĈ

arguments

. Dlate-

go gdy zwracana jest wartoĤþ

arguments[i++]

, pobierany jest argument z wy-

woãania

it.next

, a nie jeden z argumentów funkcji

values

.

RozwiĈzanie tego problemu jest proste — wystarczy zwiĈzaþ nowĈ zmiennĈ
lokalnĈ w zasičgu potrzebnego obiektu

arguments

i zadbaþ o to, aby funkcje za-

gnieİdİone uİywaãy tylko tej jawnie nazwanej zmiennej:

function values() {
var i = 0, n = arguments.length, a = arguments;
return {
hasNext: function() {
return i < n;
},
next: function() {
if(i >= n) {
throw newError("Koniec iteracji");
}
return a[i++];
}
};
}
var it = values(1, 4, 1, 4, 2, 1, 3, 5, 6);

it.next(); // 1
it.next(); // 4
it.next(); // 1

Co warto zapamičtaþ?

Q

Zwracaj uwagč na poziom zagnieİdİenia funkcji, gdy uİywasz obiektu

arguments

.

Q

ZwiĈİ z obiektem

arguments

referencjč o jawnie okreĤlonym zasičgu, aby

móc uİywaþ jej w funkcjach zagnieİdİonych.

Sposób 25. Instrukcja bind do pobierania metod o staãym odbiorcy

Sposób 25. Uİywaj instrukcji bind do pobierania metod

o staãym odbiorcy

Poniewaİ nie istnieje róİnica mičdzy metodĈ a wãaĤciwoĤciĈ, której wartoĤciĈ
jest funkcja, ãatwo moİna pobraþ metodč obiektu i przekazaþ jĈ bezpoĤrednio
jako wywoãanie zwrotne do funkcji wyİszego poziomu. Nie zapominaj jednak,
İe odbiorca pobranej funkcji nie jest na staãe ustawiony jako obiekt, z którego
tč funkcjč pobrano. WyobraĮ sobie prosty obiekt bufora ãaęcuchów znaków,
który zapisuje ãaęcuchy w tablicy, co umoİliwia ich póĮniejsze scalenie:

Poleć książkę

Kup książkę

background image

86

Rozdziaã 3. Korzystanie z funkcji

var buffer = {
entries: [],
add: function(s) {

this.entries.push(s);
},
concat: function() {
return this.entries.join("");
}
};

Wydaje sič, İe w celu skopiowania tablicy ãaęcuchów znaków do bufora moİ-
na pobraþ jego metodč

add

i wielokrotnie wywoãaþ jĈ dla kaİdego elementu

Įródãowej tablicy, uİywajĈc metody

forEach

ze standardu ES5:

var source = ["867", "-", "5309"];

source.forEach(buffer.add); // Błąd: elementy są niezdefiniowane

Jednak odbiorcĈ wywoãania

buffer.add

nie jest obiekt

buffer

. Odbiorca funkcji

zaleİy od sposobu jej wywoãania, a nie jest ona wywoãywana bezpoĤrednio
w tym miejscu. Zamiast tego zostaje ona przekazana do metody

forEach

, której

implementacja wywoãuje funkcjč w niedostčpnym dla programisty miejscu.
Okazuje sič, İe implementacja metody

forEach

jako domyĤlnego odbiorcy uİy-

wa obiektu globalnego. Poniewaİ obiekt globalny nie ma wãaĤciwoĤci

entries

,

przedstawiony kod zgãasza bãĈd. Na szczčĤcie metoda

forEach

umoİliwia poda-

nie opcjonalnego argumentu, okreĤlajĈcego odbiorcč wywoãania zwrotnego.
Dlatego moİna ãatwo rozwiĈzaþ problem:

var source = ["867", "-", "5309"];
source.forEach(buffer.add, buffer);
buffer.join(); // "867-5309"

Nie wszystkie funkcje wyİszego poziomu umoİliwiajĈ uİytkownikom okreĤle-
nie odbiorcy wywoãaę zwrotnych. Jak rozwiĈzaþ problem, gdyby metoda

forEach

nie przyjmowaãa dodatkowego argumentu okreĤlajĈcego odbiorcč? Dobrym
rozwiĈzaniem jest utworzenie funkcji lokalnej, która wywoãuje metodč

buffer.add

przy uİyciu odpowiedniej skãadni:

var source = ["867", "-", "5309"];

source.forEach(function(s) {
buffer.add(s);
});
buffer.join(); // "867-5309"

W tej wersji uİywana jest funkcja nakãadkowa, która bezpoĤrednio wywoãuje

add

jako metodč obiektu

buffer

. Zauwaİ, İe sama funkcja nakãadkowa w ogóle

nie uİywa sãowa kluczowego

this

. Niezaleİnie od sposobu wywoãania tej funkcji

nakãadkowej (moİna jĈ wywoãaþ jak zwykãĈ funkcjč, jak metodč innego
obiektu lub przy uİyciu instrukcji

call

) zawsze przekazuje ona argument do

docelowej tablicy.

Wersja funkcji wiĈİĈca odbiorcč z konkretnym obiektem jest tworzona tak czč-
sto, İe w standardzie ES5 dodano obsãugč tego wzorca w bibliotece. Obiekty

Poleć książkę

Kup książkę

background image

Sposób 26. Uİywaj metody bind do wiĈzania funkcji z podzbiorem argumentów

87

reprezentujĈce funkcje majĈ metodč

bind

, która przyjmuje obiekt odbiorcy

i generuje funkcjč nakãadkowĈ wywoãujĈcĈ pierwotnĈ funkcjč jako metodč
odbiorcy. Za pomocĈ metody

bind

moİna uproĤciþ przykãadowy kod:

var source = ["867", "-", "5309"];
source.forEach(buffer.add.bind(buffer));
buffer.join(); // "867-5309"

Pamičtaj, İe instrukcja

buffer.add.bind(buffer)

tworzy nowĈ funkcjč, zamiast

modyfikowaþ funkcjč

buffer.add

. Nowa funkcja dziaãa tak samo jak pierwotna,

ale jej odbiorca to obiekt

buffer

. Pierwotna funkcja pozostaje niezmieniona.

Oznacza to, İe:

buffer.add === buffer.add.bind(buffer); // false

Jest to subtelna, ale waİna róİnica. Oznacza to, İe metodč

bind

moİna bez-

piecznie wywoãaþ nawet dla funkcji uİywanych w innych miejscach pro-
gramu. Ma to znaczenie zwãaszcza w przypadku wspóãuİytkowanych metod
z prototypów. Taka metoda bčdzie dziaãaþ prawidãowo takİe dla obiektów po-
tomnych prototypu. Wičcej informacji o obiektach i prototypach znajdziesz
w rozdziale 4.

Co warto zapamičtaþ?

Q

Pamičtaj, İe pobranie metody nie prowadzi do ustawienia odbiorcy metody
na obiekt, z którego ona pochodzi.

Q

Przy przekazywaniu metody obiektu do funkcji wyİszego poziomu wykorzy-
staj funkcjč anonimowĈ, aby wywoãaþ metodč dla odpowiedniego odbiorcy.

Q

Stosuj metodč

bind

do szybkiego tworzenia funkcji zwiĈzanej z odpowiednim

odbiorcĈ.

Sposób 26. Uİywaj metody bind do wiĈzania funkcji z podzbiorem argumentów

Sposób 26. Uİywaj metody bind do wiĈzania funkcji

z podzbiorem argumentów (technika currying)

Metoda

bind

funkcji przydaje sič nie tylko do wiĈzania metod z odbiorcami.

WyobraĮ sobie prostĈ funkcjč tworzĈcĈ adresy URL na podstawie ich czčĤci
skãadowych.

function simpleURL(protocol, domain, path) {
return protocol + "://" + domain + "/" + path;
}

W programie potrzebne moİe byþ generowanie bezwzglčdnych adresów URL
na podstawie Ĥcieİek specyficznych dla witryny. Naturalnym sposobem na
wykonanie tego zadania jest uİycie metody

map

ze standardu ES5.

Poleć książkę

Kup książkę

background image

88

Rozdziaã 3. Korzystanie z funkcji

var urls = paths.map(function(path) {
return simpleURL("http", siteDomain, path);
});

Zauwaİ, İe w tej anonimowej funkcji w kaİdym powtórzeniu operacji przez
metodč

map

uİywane sĈ ten sam ãaęcuch znaków z protokoãem i ten sam ãaę-

cuch znaków z domenĈ witryny. Dwa pierwsze argumenty funkcji

simpleURL

sĈ niezmienne w kaİdej iteracji. Potrzebny jest tylko trzeci argument. Moİna
wykorzystaþ metodč

bind

funkcji

simpleURL

, aby automatycznie uzyskaþ po-

trzebnĈ funkcjč:

var urls = paths.map(simpleURL.bind(null, "http", siteDomain));

Wywoãanie

simpleURL.bind

tworzy nowĈ funkcjč, która deleguje zadania do funkcji

simpleURL

. Jak zawsze w pierwszym argumencie metody

bind

podawany jest od-

biorca. Poniewaİ funkcja

simpleURL

go nie potrzebuje, moİna podaþ tu dowolnĈ

wartoĤþ (standardowo uİywane sĈ wartoĤci

null

i

undefined

). Argumenty przeka-

zywane do funkcji

simpleURL

to wynik poãĈczenia pozostaãych argumentów

funkcji

simpleURL.bind

z argumentami przekazanymi do nowej funkcji. Ozna-

cza to, İe gdy funkcja utworzona za pomocĈ instrukcji

simpleURL.bind

jest

wywoãywana z jednym argumentem

path

, w wyniku oddelegowania zadania

wywoãanie wyglĈda tak:

simpleURL("http", siteDomain, path)

.

Technika wiĈzania funkcji z podzbiorem argumentów to currying (nazwa pocho-
dzi od logika Haskella Curry’ego, który spopularyzowaã tč metodč w matematy-
ce). Currying pozwala na zwičzãe implementowanie delegowania i nie wymaga
tak duİo szablonowego kodu jak jawne tworzenie funkcji nakãadkowych.

Co warto zapamičtaþ?

Q

Za pomocĈ metody

bind

moİna utworzyþ funkcjč delegujĈcĈ zadania, prze-

kazujĈcĈ staãy podzbiór wymaganych argumentów. Ta technika to currying.

Q

Aby za pomocĈ tej techniki utworzyþ funkcjč, która ignoruje odbiorcč,
jako reprezentujĈcy go argument podaj wartoĤþ

null

lub

undefined

.

Sposób 27. Wybieraj domkničcia zamiast ãaęcuchów znaków

do hermetyzowania kodu

Funkcje to wygodny sposób przechowywania kodu w postaci struktur danych
i póĮniejszego uruchamiania go. Pozwala to na stosowanie zwičzãych abstrak-
cyjnych instrukcji wyİszego poziomu, takich jak

map

i

forEach

, oraz jest istotĈ

asynchronicznego wykonywania operacji wejĤcia-wyjĤcia w JavaScripcie (zo-
bacz rozdziaã 7.). JednoczeĤnie moİna teİ zapisaþ kod jako ãaęcuch znaków
i przekazywaþ go do instrukcji

eval

. ProgramiĤci stojĈ wičc przed wyborem,

czy zapisaþ kod jako funkcjč, czy jako ãaęcuch znaków.

Poleć książkę

Kup książkę

background image

Sposób 27. Wybieraj domkničcia zamiast ãaęcuchów znaków do hermetyzowania kodu

89

Gdy masz wĈtpliwoĤci, stosuj funkcje. âaęcuchy znaków zapewniajĈ znacznie
mniejszĈ swobodč. Wynika to z waİnego powodu — nie sĈ domkničciami.

Przyjrzyj sič prostej funkcji wielokrotnie powtarzajĈcej okreĤlonĈ przez uİyt-
kownika operacjč:

function repeat(n, action) {
for (var i = 0; i < n; i++) {
eval(action);
}
}

W zasičgu globalnym ta funkcja dziaãa poprawnie, poniewaİ wszystkie refe-
rencje do zmiennych wystčpujĈce w ãaęcuchu znaków sĈ interpretowane
przez instrukcjč

eval

jako zmienne globalne. Na przykãad w skrypcie, który

mierzy szybkoĤþ dziaãania funkcji, moİna wykorzystaþ zmienne globalne

start

i

end

do przechowywania pomiarów czasu:

var start = [], end = [], timings = [];
repeat(1000,
"start.push(Date.now()); f(); end.push(Date.now())");
for (var i = 0, n = start.length; i < n; i++) {
timings[i] = end[i] - start[i];
}

Jednak ten skrypt jest podatny na problemy. Po przeniesieniu kodu do funkcji

start

i

end

nie bčdĈ juİ zmiennymi globalnymi:

function benchmark() {
var start = [], end = [], timings = [];
repeat(1000,
"start.push(Date.now()); f(); end.push(Date.now())");
for (var i = 0, n = start.length; i < n; i++) {
timings[i] = end[i] - start[i];
}
return timings;
}

Ta funkcja powoduje, İe instrukcja

repeat

wykorzystuje referencje do zmien-

nych globalnych

start

i

end

. W najlepszym przypadku jedna z tych zmien-

nych nie bčdzie istnieþ, a wywoãanie funkcji

benchmark

doprowadzi do bãčdu

ReferenceError

. JeĤli programista bčdzie miaã pecha, kod wywoãa instrukcjč

push

dla globalnych obiektów zwiĈzanych z nazwami

start

i

end

, a program

bčdzie dziaãaã nieprzewidywalnie.

Bardziej odporny na bãčdy interfejs API przyjmuje funkcjč zamiast ãaęcucha
znaków:

function repeat(n, action) {
for (var i = 0; i < n; i++) {

action();
}
}

Poleć książkę

Kup książkę

background image

90

Rozdziaã 3. Korzystanie z funkcji

Dzički temu w skrypcie

benchmark

moİna bezpiecznie uİywaþ zmiennych lo-

kalnych z domkničcia przekazywanego jako wielokrotnie uruchamiane wy-
woãanie zwrotne:

function benchmark() {
var start = [], end = [], timings = [];
repeat(1000, function() {
start.push(Date.now());
f();
end.push(Date.now());
});
for (var i = 0, n = start.length; i < n; i++) {
timings[i] = end[i] - start[i];
}
return timings;
}

Inny problem z instrukcjĈ

eval

polega na tym, İe silniki o wysokiej wydajnoĤci

majĈ zwykle wičksze problemy z optymalizacjĈ kodu z ãaęcuchów znaków,
poniewaİ kod Įródãowy moİe nie byþ dostčpny dla kompilatora na tyle wcze-
Ĥnie, by moİna byão w odpowiednim momencie przeprowadziþ optymalizacjč.
Wyraİenia funkcyjne moİna kompilowaþ jednoczeĤnie z kodem, w którym wy-
stčpujĈ. Dlatego znacznie ãatwiej sič je kompiluje w standardowy sposób.

Co warto zapamičtaþ?

Q

Nigdy nie stosuj lokalnych referencji w ãaęcuchach znaków przekazywanych
do interfejsu API, który wykonuje kod z ãaęcucha za pomocĈ instrukcji

eval

.

Q

Preferuj interfejsy API, które przyjmujĈ wywoãywane funkcje zamiast ãaęcu-
chów znaków przekazywanych do instrukcji

eval

.

Sposób 28. Unikaj stosowania metody toString funkcji

Funkcje w JavaScripcie majĈ niezwykãĈ cechč — umoİliwiajĈ wyĤwietlenie
swojego kodu Įródãowego jako ãaęcucha znaków:

(function(x) {
returnx + 1;

}).toString(); // "function (x) {\n return x + 1;\n}"

WyĤwietlanie kodu Įródãowego funkcji za pomocĈ mechanizmu refleksji daje
duİo moİliwoĤci, a pomysãowi hakerzy potrafiĈ znaleĮþ ciekawe sposoby ich
wykorzystania. Jednak metoda

toString

funkcji ma powaİne ograniczenia.

Przede wszystkim standard ECMAScript nie okreĤla İadnych wymagaę wobec
ãaęcuchów znaków zwracanych przez metodč

toString

funkcji. To oznacza,

İe róİne silniki JavaScriptu mogĈ zwracaþ odmienne ãaęcuchy znaków.
Moİliwe nawet, İe zwrócony tekst w rzeczywistoĤci nie bčdzie podobny do
kodu danej funkcji.

Poleć książkę

Kup książkę

background image

Sposób 28. Unikaj stosowania metody toString funkcji

91

W praktyce silniki JavaScriptu próbujĈ wyĤwietliþ wiernĈ reprezentacjč kodu
Įródãowego funkcji, o ile napisano jĈ w czystym JavaScripcie. Nie sprawdza
sič to na przykãad dla funkcji generowanych przez wbudowane biblioteki
Ĥrodowiska hosta:

(function(x) {
returnx + 1;
}).bind(16).toString(); // "function (x) {\n [native code]\n}"

Poniewaİ w wielu Ĥrodowiskach hosta funkcja

bind

jest zaimplementowana

w innym jčzyku programowania (zwykle w C++), zwracana jest skompilo-
wana funkcja bez kodu Įródãowego w JavaScripcie, który Ĥrodowisko mo-
gãoby wyĤwietliþ.

Poniewaİ przeglĈdarki wedãug standardu mogĈ w odpowiedzi na wywoãanie
funkcji

toString

zwracaþ inne dane, zbyt ãatwo jest napisaþ program, który

dziaãa prawidãowo w jednym systemie, ale niepoprawnie w innym. Nawet
drobne rozbieİnoĤci w implementacjach JavaScriptu (na przykãad sposób for-
matowania odstčpów) mogĈ zaburzyþ dziaãanie programu, który jest wraİliwy
na szczegóãy zapisu kodu Įródãowego funkcji.

Ponadto kod Įródãowy generowany przez metodč

toString

nie zwraca repre-

zentacji domkničcia z zachowaniem wartoĤci zwiĈzanych ze zmiennymi
wewnčtrznymi. Oto przykãad:

(function(x) {

return function(y) {

return x + y;

}
})(42).toString(); // "function (y) {\n return x + y;\n}"

Zauwaİ, İe w wynikowym ãaęcuchu znaków wystčpuje zmienna

x

, choþ

funkcja jest domkničciem wiĈİĈcym

x

z wartoĤciĈ

42

.

Te ograniczenia sprawiajĈ, İe trudno jest w przydatny i niezawodny sposób
pobieraþ kod Įródãowy funkcji. Dlatego zwykle warto unikaþ opisanej techniki.
Do bardzo zaawansowanych operacji pobierania kodu Įródãowego funkcji
naleİy stosowaþ starannie napisane parsery i biblioteki przetwarzajĈce
kod w JavaScripcie. W razie wĈtpliwoĤci najbezpieczniej jest traktowaþ
funkcje JavaScriptu jak abstrakcyjne struktury, których nie naleİy dzieliþ
na fragmenty.

Co warto zapamičtaþ?

Q

Silniki JavaScriptu nie muszĈ wiernie zwracaþ kodu Įródãowego funkcji
po wywoãaniu metody

toString

.

Q

Nigdy nie polegaj na szczegóãach z pobranego kodu Įródãowego funkcji,
poniewaİ wywoãanie metody

toString

w róİnych silnikach moİe dawaþ od-

mienne wyniki.

Poleć książkę

Kup książkę

background image

92

Rozdziaã 3. Korzystanie z funkcji

Q

Tekst zwracany przez metodč

toString

nie pokazuje wartoĤci zmiennych

lokalnych z domkničcia.

Q

Zwykle warto unikaþ wywoãywania metody

toString

dla funkcji.

Sposób 29. Unikaj niestandardowych wãaĤciwoĤci

przeznaczonych do inspekcji stosu

Wiele Ĥrodowisk JavaScriptu w przeszãoĤci udostčpniaão mechanizmy do in-
spekcji stosu wywoãaę, czyli ãaęcucha obecnie wykonywanych aktywnych
funkcji (wičcej o stosie wywoãaę dowiesz sič ze sposobu 64.). W starszych
Ĥrodowiskach hosta kaİdy obiekt

arguments

ma dwie dodatkowe wãaĤciwoĤci:

arguments.callee

(okreĤla funkcjč wywoãanĈ z argumentami

arguments

) i

arguments.

´

caller

(okreĤla funkcjč wywoãujĈcĈ). Pierwsza z tych wãaĤciwoĤci nadal jest

obsãugiwana w wielu Ĥrodowiskach, jednak sãuİy tylko do rekurencyjnego
wskazywania funkcji anonimowych w nich samych.

var factorial = (function(n) {
return (n <= 1) ? 1 : (n * arguments.callee(n - 1));
});

Nie jest to specjalnie przydatne, poniewaİ ãatwiej jest w funkcji wywoãaþ jĈ
za pomocĈ nazwy.

function factorial(n) {
return (n <= 1) ? 1 : (n * factorial(n - 1));
}

WãaĤciwoĤþ

arguments.caller

daje wičksze moİliwoĤci. Wskazuje funkcjč, w której

znalazão sič wywoãanie z danym obiektem

arguments

. Z powodów bezpieczeę-

stwa mechanizm ten zostaã usuničty z wičkszoĤci Ĥrodowisk, tak wičc moİe
okazaþ sič niedostčpny. Wiele Ĥrodowisk JavaScriptu udostčpnia podobnĈ
wãaĤciwoĤþ dla obiektów funkcyjnych — niestandardowĈ, ale czčsto spotyka-
nĈ wãaĤciwoĤþ

caller

. OkreĤla ona jednostkč, która wywoãaãa danĈ funkcjč.

function revealCaller() {
return revealCaller.caller;
}

function start() {
return revealCaller();
}

start() === start; // true

Dobrym pomysãem moİe wydawaþ sič wykorzystanie tej wãaĤciwoĤci do pobie-
rania Ĥladu stosu (struktury danych zawierajĈcej obecny stan stosu wywoãaę).
Budowanie Ĥladu stosu na pozór jest bardzo proste.

function getCallStack() {
var stack = [];

Poleć książkę

Kup książkę

background image

Sposób 29. Unikaj niestandardowych wãaĤciwoĤci przeznaczonych do inspekcji stosu

93

for (var f = getCallStack.caller; f; f = f.caller) {
stack.push(f);
}
return stack;
}

Dla prostych stosów wywoãaę funkcja

getCallStack

dziaãa poprawnie.

function f1() {
return getCallStack();
}

function f2() {
return f1();
}

var trace = f2();

trace; // [f1, f2]

Jednak dziaãanie funkcji

getCallStack

ãatwo jest zakãóciþ. JeĤli dana funkcja

wystčpuje w stosie wywoãaę wičcej niİ raz, kod odpowiedzialny za inspekcjč
stosu wpada w pčtlč.

function f(n) {
return n === 0 ? getCallStack() : f(n - 1);
}

var trace = f(1); // Pętla nieskończona

W czym tkwi problem? Poniewaİ funkcja

f

rekurencyjnie wywoãuje samĈ siebie,

wãaĤciwoĤþ

caller

jest automatycznie ustawiana na

f

. Dlatego pčtla w funkcji

getCallStack

nieustannie szuka funkcji

f

. Nawet jeĤli programista spróbuje

wykrywaþ takie cykle, niedostčpne bčdĈ informacje o tym, jaka funkcja wy-
woãaãa funkcjč

f

, zanim funkcja

f

wywoãaãa samĈ siebie. Informacje o reszcie

stosu wywoãaę zostajĈ wičc utracone.

Wszystkie wymienione mechanizmy inspekcji stosu sĈ niestandardowe oraz
majĈ ograniczonĈ przenoĤnoĤþ i zastosowania. Ponadto w standardzie ES5
sĈ one niedozwolone w funkcjach w trybie strict. Próby dostčpu do wãaĤciwoĤci

caller

i

callee

funkcji w trybie strict oraz do obiektów

arguments

powodujĈ bãĈd.

function f() {
"use strict";
return f.caller;
}

f(); // Błąd — nie można używać właściwości caller funkcji w trybie strict

Najlepsze podejĤcie polega na rezygnacji z inspekcji stosu. JeĤli potrzebujesz
sprawdzaþ stos na potrzeby debugowania, znacznie lepiej jest uİyþ interak-
tywnego debugera.

Poleć książkę

Kup książkę

background image

94

Rozdziaã 3. Korzystanie z funkcji

Co warto zapamičtaþ?

Q

Unikaj niestandardowych wãaĤciwoĤci

arguments.caller

i

arguments.callee

,

poniewaİ w niektórych Ĥrodowiskach sĈ niedostčpne.

Q

Unikaj niestandardowej wãaĤciwoĤci

caller

funkcji, poniewaİ nie zawsze

zwraca kompletne informacje o stosie.

Poleć książkę

Kup książkę

background image

Skorowidz

A

abstrakcje wyİszego poziomu, 76
aktor, 112
API, 151
argument, 81
arnoĤþ funkcji, 79
ASCII, 43
aspekty pragmatyczne, 13
asynchroniczne

pčtle, 190
wywoãania zwrotne, 201

atrapa, 167
atrybut, 135
automatyczne dodawanie Ĥredników, 37

B

bezstanowy interfejs API, 161
biblioteka, 151

Canvas, 161

bitowe

operatory arytmetyczne, 28
wyraİenie OR, 26

blok catch, 59
blokowanie kolejki zdarzeę, 193
bãĈd

parsowania, 38, 42
skãadni, 66
TypeError, 101

bãčdy ignorowane, 187
BMP, Basic Multilingual Plane, 44

C

currying, 87, 88

D

debugowanie, 63, 64
dodawanie argumentów, 157
domkničcia, 54, 88
dziedziczenie

implementacji, 95
po klasach standardowych, 117

E

ECMA, 13
ECMAScript, 14
enumeracja, 136

F

format MediaWiki, 165
funkcja, 71

Alert, 160
averageScore, 48
benchmark, 89
downloadAllAsync, 186, 188, 199
downloadAsync, 182, 184
downloadCachingAsync, 202
downloadOneAsync, 192
eval, 67–69
extend, 160
fail, 39
getCallStack, 93
isNaN, 29
make, 55
MEDIAWIKI, 165
negative, 192
next, 196
Number, 34
onsuccess, 198

Poleć książkę

Kup książkę

background image

208

Skorowidz

funkcja

sandwichMaker, 55
score, 48
select, 206
showContents, 185
simpleURL, 88
status, 53
trimSections, 58
tryNextURL, 191
User, 96, 102

funkcje

asynchroniczne, 180
blokujĈce, 180
rekurencyjne, 193
synchroniczne, 180
wariadyczne, 79, 81
wywoãywane zwrotnie, 74
wyİszego poziomu, 74

G

graf

sceny, 111
sieci spoãecznoĤciowej, 137

H

hermetyzowanie kodu, 88
hierarchia dziedziczenia, 115
hoisting, 57

zmiennych, 58

I

idiom, 151
IIFE, 23, 40, 61
implementowanie sãowników, 123
instrukcja

__proto__, 95
apply, 79
bind, 85
break, 42
call, 77
continue, 42
eval, 90
getPrototypeOf, 95
if, 188
new, 101
Object.getPrototypeOf, 99
prototype, 95
return, 57
throw, 42

var, 39
with, 52, 53

interfejs API, 151
interfejsy

bezstanowe, 161
stanowe, 161
elastyczne, 164

introspekcja, 119
iterator, 84

J

jawna konwersja, 36
jednostki kodowe, 43

K

klasa, 98

Array, 118, 146
Dict, 124
MWPage, 165
User, 106

kodowanie

o zmiennej dãugoĤci, 45
znaków, 43

koercja, 171
kolejka zdarzeę, 179, 193
kolekcja, 123
kolekcje uporzĈdkowane, 132
konstrukcja try…catch, 59
konstruktor, 71

klasy Array, 148

kontekst, 112
konwencje spójne, 151
konwersja typu, 28

jawna, 36
niejawna, 35

L

liczba argumentów, 79
liczby

o podwójnej precyzji, 26
zmiennoprzecinkowe, 24

literaãy tablicowe, 148

â

ãaęcuch

zasičgu, 52
znaków, 30, 32, 43–45
metod, 174

Poleć książkę

Kup książkę

background image

Skorowidz

209

ãĈczenie

metod w ãaęcuch, 175
obietnic, 204
plików, 23

ãĈcznoĤþ lewostronna, 28

M

mapy deskryptorów wãaĤciwoĤci, 126
mechanizm naprawiania bãčdów, 38
metadane, 135
metoda, 71

bind, 87
call, 77, 82
concat, 147
enable, 168, 172
forEach, 78, 146
hasOwnProperty, 128
inNetwork, 195
Object.create, 102, 114
pick, 139
postMessage, 194
replace, 174
shift, 82
slice, 83, 148
toString, 25, 30, 90
toUpperCase, 33
valueOf, 30, 31, 34

metody

dla niestandardowego odbiorcy, 77
do obsãugi iteracji, 142
klasy Array, 146, 148
niedeterministyczne, 139
o staãym odbiorcy, 85
w prototypach, 103

modyfikowanie

obiektu, 82, 136
wãaĤciwoĤci __proto__, 100

monkey patching, 120

N

nakãadki obiektowe, 32
naprawianie bãčdów, 38
narzčdzie lint, 51
nazwa wãaĤciwoĤci, 115
niejawna konwersja typu, 27
niejawne

przenoszenie deklaracji zmiennych,

57

tworzenie nakãadek obiektowych, 34
wiĈzanie obiektu, 109

nieprzenoĤne okreĤlanie zasičgu, 62, 65
niestandardowy odbiorca, 77

O

obiekt, 95

arguments, 82, 84
this, 109, 177
typu String, 32
XMLHttpRequest, 182

obiekty

globalne, 48
z opcjami, 157

obietnice, 203
obsãuga

bãčdów, 187
iteracji, 142
ãaęcuchów metod, 174

ograniczone konstrukcje, 41
okreĤlanie typu na podstawie struktury,

166

operacja ãĈczna lewostronnie, 28
operator

+, 30
++, 42
identycznoĤci, 34
równoĤci, 33, 35
typeof, 32
undefined, 32

operatory

arytmetyczne bitowe, 28
przesuničcia, 28

osadzany jčzyk skryptowy, 179

P

parametr formalny, 81
pary surogatów, 46
pčtla

for, 60, 140, 142
for…in, 134, 135, 140
while, 140
zdarzeę, 179, 181

pliki o róİnych trybach, 23
pobieranie

metod, 85
prototypów obiektów, 97

podstawa, 25
podwójna precyzja, 25
praca na odlegãoĤþ, 120
prawo ãĈcznoĤci, 26
predykat, 143

Poleć książkę

Kup książkę

background image

210

Skorowidz

programowanie

asynchroniczne, 187
defensywne, 172
obiektowe, 71

prototyp, 95, 119

Array.prototype, 126
Object.prototype, 134

prototypy null, 126
przechowywanie

metod

w egzemplarzach, 104
w prototypie, 105

prywatnych danych, 105
stanu egzemplarza, 107

w egzemplarzach, 108
w prototypie, 108

przeciĈİony operator, 30
przekazywanie argumentów, 157
przepeãnienie stosu, 192
przesãanianie konstruktora, 103
przestrzeę nazw, 48
przetwarzanie skrócone, 145

R

referencje do obiektu arguments, 84
rekurencja, 190

S

scalanie skryptów, 22, 24
semantyka, 13
skãadnia, 13
sãowniki, 123
sãowo kluczowe

arguments, 81
const, 20
new, 101
return, 41
this, 72, 86
var, 64
with, 51

standard

ECMAScript, 13, 19
IEEE, 29

stanowe interfejsy API, 162
stos wywoãaę, 92, 191, 193
stosowanie

domkničþ, 105
enumerowanych wãaĤciwoĤci, 134
instrukcji Object.getPrototypeOf, 99
metody toString, 90

nazwanych wyraİeę funkcyjnych, 62
rekurencji, 190
tablic, 132
techniki monkey patching, 120

struktura, 164
styl pãynny, 176
systemy modularne, 23

ģ

Ĥlad stosu, 93
Ĥrednik, 37
Ĥrodowisko leksykalne, 52

T

tablice, 123
technika monkey patching, 120
tryb strict, 21, 23
tworzenie

abstrakcji, 76
asynchronicznych pčtli, 190
funkcji wariadycznych, 81
kolekcji, 132
pčtli, 145
zmiennych globalnych, 47
zmiennych lokalnych, 48

typy

oparte na strukturze, 169
proste, 32

U

UCS-2, 43
Unicode, 43
UTF-16, 45

W

wartoĤci

logiczne, 31
oznaczajĈce faãsz, 31

wartoĤþ

NaN, 29
null, 28, 63
ostateczna, 204
scores.length, 141
true, 31
undefined, 32, 153, 159

wĈtek, 180
wektor bitowy, 167
wersja JavaScriptu, 19

Poleć książkę

Kup książkę

background image

Skorowidz

211

wiĈzanie funkcji, 87, 88
wãaĤciwoĤci

enumerowane, 134
wewnčtrzne, 117

wãaĤciwoĤþ

__proto__, 97, 100, 127, 130
caller, 94
info, 53
length, 168
prototype, 96

wspóãbieİne pobieranie plików, 197
wspóãbieİnoĤþ, 14

oparta na pčtli zdarzeę, 179

wspóãrzčdna kodowa znaku, 43
wspóãrzčdne kodowe Unicode, 46
wykonywanie funkcji rekurencyjnej,

193

wypeãniacz, 121
wyraİenia

funkcyjne, 23, 56

anonimowe, 64
natychmiast wywoãywane, 61
nazwane, 62

IIFE, 59

wyraİenie OR, 25
wyĤcig do danych, 199
wywoãania

asynchroniczne, 183
bezpoĤrednie, 70
funkcji, 71, 79
konstruktorów, 71
metod, 71, 77
poĤrednie, 70
zwrotne, 183

nazwane, 183
zagnieİdİone, 183

wywoãanie downloadAsync, 183

Z

zagnieİdİanie, 184

deklaracji funkcji, 65

zasičg

blokowy, 57
leksykalny, 57
lokalny, 59
zmiennych, 47

zaĤmiecanie przez prototypy, 125, 126,

128

zbiór ãaęcuchów znaków, 168
zdarzenia, 180
zmienna arguments, 21
zmienne

globalne, 23, 47
lokalne, 50, 67

znak

(, 38
., 46
/, 39
[, 38
;, 41

znaki niebezpieczne, 40
zwracanie obiektu this, 177

Poleć książkę

Kup książkę

background image

212

Skorowidz

Poleć książkę

Kup książkę

background image
background image

Wyszukiwarka

Podobne podstrony:
Efektywny JavaScript 68 sposobow wykorzystania potegi jezyka 2
Efektywny JavaScript 68 sposobow wykorzystania potegi jezyka efprjs
Efektywny JavaScript 68 sposobow wykorzystania potegi jezyka
praktyczny sposób wykorzystania narzedzi pr, marketing i reklama, perswazja, reklama, marketing, jęz
Faktyczny sposób wykorzystania nieruchomości przed wejściem planu w życie
Prawo-autorskie-sposoby-wykorzystania-utworow
Sposoby wykorzystywania żywności w biotechnologii
Różne sposoby wykorzystania kultury ludowej w literaturze polskiej na wybranych przykładach
Jak opanowac dowolny jezyk obcy Jak przyjemnie i efektywnie opanowac dowolny jezyk wykorzystujac to
101 sposobów wykorzystania niesamowitych olejków eterycznych
Inne sposoby wykorzystania olejków eterycznych
Trzy sposoby wykorzystania wysokiej wartości czułości ISO
Wykorzystanie potegi run dla zdrowia milosci fortuny
M Szczepanczyk INNOWACYJNE SPOSOBY WYKORZYSTANIA MEDIÓW SPOŁECZNOŚCIOWYCH W KOMUNIKACJI WEWNĘTRZNEJ
Efektywny Python 59 sposobow na lepszy kod

więcej podobnych podstron