informatyka javascript mocne strony douglas crockford ebook

background image

JavaScript - mocne strony

Autor: Douglas Crockford
ISBN: 978-83-246-1998-6
Tytu³ orygina³u:

JavaScript: The Good Parts

Format: 168x237, stron: 160

Poznaj doskona³¹ u¿ytecznoœæ jêzyka JavaScript!

•

Jak efektywnie wykorzystaæ najlepsze funkcje JavaScript?

•

Jak pisaæ programy, aby ustrzec siê b³êdów?

•

Jak zdefiniowaæ podzbiór jêzyka i tworzyæ idealne aplikacje?

Warto poznaæ jêzyk JavaScript, poniewa¿ stanowi on jedno z wa¿niejszych narzêdzi
w informatyce — dziêki temu, ¿e jest jednoczeœnie podstawowym i domyœlnym jêzykiem
przegl¹darek internetowych oraz jêzykiem programowania. JavaScript pozwala na
tworzenie wydajnego kodu bibliotek obiektowych czy aplikacji opartych na technice
AJAX. Jego skrypty s³u¿¹ najczêœciej do zapewniania interaktywnoœci, sprawdzania
poprawnoœci formularzy oraz budowania elementów nawigacyjnych. Doœæ ³atwa
sk³adnia sprawia, ¿e pisanie pe³noprawnych i wydajnych aplikacji w tym jêzyku nie jest
trudne nawet dla pocz¹tkuj¹cych programistów.

Ksi¹¿ka „JavaScript — mocne strony” to wyj¹tkowy podrêcznik do nauki tego
popularnego, dynamicznego jêzyka programowania. Dowiesz siê z niej, jak efektywnie
wykorzystaæ wszystkie jego mocne strony (m.in. funkcje, dynamiczne obiekty, litera³y
obiektowe) oraz jak unikaæ pu³apek. Poznasz elementy sk³adowe jêzyka oraz sposoby
ich ³¹czenia, zrozumiesz, na czym polega dziedziczenie prototypowe, w jaki sposób
brak kontroli typów ma pozytywny wp³yw na pisanie aplikacji oraz dlaczego stosowanie
zmiennych globalnych jako podstawowego modelu programowania nie jest dobrym
pomys³em. Znaj¹c wszelkie ograniczenia jêzyka JavaScript, bêdziesz móg³
profesjonalnie wykorzystaæ jego najlepsze czêœci.

•

Gramatyka jêzyka JavaScript

•

Obiekty i funkcje

•

Rekurencja

•

Kaskadowe ³¹czenie wywo³añ

•

Litera³y obiektowe

•

Dziedziczenie — pseudoklasyczne, prototypowe, funkcyjne

•

Tablice

•

Wyra¿enia regularne

•

Klasa znaków i kwantyfikator wyra¿enia regularnego

Nie traæ czasu — siêgaj tylko po to, co najlepsze w jêzyku JavaScript!

background image

5

Spis tre

ļci

Wst

ýp ........................................................................................................................................9

1. Mocne strony ................................................................................................................11

Dlaczego JavaScript?

12

Analizujñc JavaScript

12

Prosta platforma testowa

14

2. Gramatyka ................................................................................................................... 15

Biaäe znaki

15

Nazwy

16

Liczby

17

ãaþcuchy znakowe

18

Instrukcje

20

WyraĔenia

24

Literaäy

27

Funkcje

28

3. Obiekty .........................................................................................................................29

Literaäy obiektowe

29

Pobieranie

30

Modyfikacja

30

Referencja

31

Prototyp

31

Refleksja

32

Wyliczanie

32

Usuwanie

33

Ograniczanie liczby zmiennych globalnych

33

4. Funkcje .........................................................................................................................35

Obiekty funkcji

35

Literaä funkcji

36

Wywoäanie

36

Argumenty

39

background image

6

_

Spis tre

ļci

Powrót z funkcji

40

Wyjñtki

40

Rozszerzanie typów

41

Rekurencja

42

Zasiög

43

Domkniöcia

44

Wywoäania zwrotne

47

Moduä

47

Kaskadowe äñczenie wywoäaþ

49

Funkcja curry

50

Spamiötywanie

51

5. Dziedziczenie ...............................................................................................................53

Dziedziczenie pseudoklasyczne

53

OkreĈlenia obiektów

56

Dziedziczenie prototypowe

56

Dziedziczenie funkcyjne

58

CzöĈci

61

6. Tablice ..........................................................................................................................63

Literaäy tablicowe

63

DäugoĈè tablicy

64

Usuwanie elementów

65

Wyliczanie

65

Problem z rozpoznawaniem typu

65

Metody

66

Wymiary

67

7. Wyra

żenia regularne ...................................................................................................69

Przykäad

70

Tworzenie

74

Elementy

75

8. Metody ......................................................................................................................... 81

9. Styl ................................................................................................................................ 97

10. Najpi

ýkniejsze cechy jýzyka .......................................................................................101

background image

Spis tre

ļci

_

7

Dodatek A K

ĥopotliwe cechy jýzyka .................................................................................... 105

Dodatek B Nietrafione cechy j

ýzyka .....................................................................................113

Dodatek C JSLint ....................................................................................................................119

Dodatek D Diagramy sk

ĥadni ............................................................................................... 129

Dodatek E JSON .................................................................................................................... 139

Skorowidz ............................................................................................................................. 149

background image

53

ROZDZIA

Ĥ 5.

Dziedziczenie

Dziedziczenie jest waĔnym zagadnieniem w wiökszoĈci jözyków programowania.

W jözykach klasycznych (takich jak Java) dziedziczenie ma dwa gäówne zadania. Po pierwsze,
jest formñ wielokrotnego uĔycia kodu. JeĈli nowa klasa jest podobna do istniejñcej, wystarczy
okreĈliè dzielñce je róĔnice. Ponowne wykorzystanie kodu jest waĔne, poniewaĔ pozwala zmniej-
szyè koszty wytwarzania oprogramowania. Drugñ zaletñ dziedziczenia jest to, Ĕe zawiera ono
w sobie specyfikacjö systemu typów. Uwalnia to programistów w duĔej mierze od koniecznoĈci
rzutowania z jednego typu na drugi, co jest istotnñ zaletñ, poniewaĔ rzutowanie podwaĔa
caäñ wartoĈè bezpieczeþstwa systemu typów.

JavaScript, jako jözyk bez kontroli typów, nigdy nie wymaga rzutowania. Hierarchia dziedzi-
czenia obiektu nie ma tu znaczenia. WaĔne jest, co obiekty potrafiñ robiè, a nie po czym
dziedziczñ.

JavaScript posiada duĔo bogatszy zasób moĔliwoĈci ponownego wykorzystania kodu. MoĔe
naĈladowaè klasyczne wzorce, ale dostarcza równieĔ innych, bardziej ekspresyjnych. Zbiór
moĔliwych wzorców dziedziczenia w JavaScripcie jest bardzo szeroki. W tym rozdziale przyj-
rzymy siö kilku najprostszym przypadkom. DuĔo bardziej skomplikowane sñ równieĔ moĔ-
liwe, ale zazwyczaj lepiej jest trzymaè siö tych najprostszych.

W klasycznych jözykach obiekty sñ instancjami klas, a klasa moĔe dziedziczyè po innej klasie.
JavaScript jest jözykiem prototypowym, co oznacza, Ĕe obiekty dziedziczñ bezpoĈrednio z in-
nych obiektów.

Dziedziczenie pseudoklasyczne

Jözyk JavaScript ma wewnötrznie gäöboko rozdartñ naturö. Jego mechanizm prototypowy jest
zaciemniany przez niektóre skomplikowane elementy skäadni, które wyglñdajñ bardziej kla-
sycznie. Zamiast pozwoliè obiektom dziedziczyè bezpoĈrednio z innych obiektów, JavaScript
wprowadza niepotrzebny poziom abstrakcji, w którym obiekty tworzone sñ przy uĔyciu
funkcji konstruktorów.

Kiedy tworzony jest obiekt funkcji, konstruktor

Function

zwracajñcy obiekt funkcji wykonuje

kod podobny do poniĔszego:

this.prototype = {constructor: this};

background image

54

_

Rozdzia

ĥ 5. Dziedziczenie

Nowy obiekt funkcji otrzymuje wäaĈciwoĈè

prototype

, której wartoĈciñ jest obiekt posiadajñcy

wäaĈciwoĈè

constructor

, której to z kolei wartoĈciñ jest nowy obiekt funkcji. Obiekt

prototype

jest miejscem, gdzie zäoĔone majñ byè odziedziczone wäaĈciwoĈci. KaĔda funkcja otrzymuje
obiekt

prototype

, poniewaĔ jözyk nie posiada sposobu okreĈlenia, które funkcje sñ przezna-

czone do uĔycia w roli konstruktorów. WäaĈciwoĈè

constructor

nie jest zbyt uĔyteczna. To

obiekt

prototype

ma znaczenie.

Kiedy funkcja jest wywoäywana wedäug wzorca wywoäania konstruktora z uĔyciem säowa

new

, zmienia siö sposób wykonania funkcji. Gdyby operator

new

byä metodñ, a nie operatorem,

mógäby byè zaimplementowany w ten sposób:

Function.method('new', function () {

// Tworzymy nowy obiekt dziedzicz

ący z prototypu konstruktora.

var that = Object.beget(this.prototype);

// Wywo

áujemy konstruktor, wiąĪąc this do nowego obiektu.

var other = this.apply(that, arguments);

// Je

Ğli zwracana wartoĞü nie jest obiektem,

// podmie

Ĕ ją na nowo utworzony obiekt.

return (typeof other === 'object' && other) || that;
});

MoĔemy zdefiniowaè konstruktor i rozszerzyè jego prototyp:

var Mammal = function (name) {
this.name = name;
};

Mammal.prototype.get_name = function () {
return this.name;
};

Mammal.prototype.says = function () {
return this.saying || '';
};

Tworzymy instancjö:

var myMammal = new Mammal('Mój ssak');
var name = myMammal.get_name(); // 'Mój ssak'

Nastöpnie moĔemy utworzyè innñ pseudoklasö dziedziczñcñ z

Mammal

, definiujñc jej konstruktor

i zastöpujñc jej prototyp instancjñ

Mammal

:

var Cat = function (name) {
this.name = name;
this.saying = 'miau';
};

// Zast

Ċpujemy Cat.prototype instancją Mammal

Cat.prototype = new Mammal();

// Rozszerzamy nowy prototyp metodami purr i get_name

Cat.prototype.purr = function (n) {
var i, s = '';
for (i = 0; i < n; i += 1) {

background image

Dziedziczenie pseudoklasyczne

_

55

if (s) {
s += '-';
}
s += 'r';
}
return s;
};
Cat.prototype.get_name = function () {
return this.says() + ' ' + this.name + ' ' + this.says();
};

var myCat = new Cat('Kicia');
var says = myCat.says(); // 'miau'
var purr = myCat.purr(5); // 'r-r-r-r-r'
var name = myCat.get_name(); // 'miau Kicia miau'

Pseudoklasyczne dziedziczenie miaäo w zamiarach wyglñdaè bardziej obiektowo, lecz w prak-
tyce wyglñda dziwnie i obco. CzöĈè brzydoty tego rozwiñzania moĔemy ukryè, uĔywajñc metody

method

i definiujñc metodö

inherits

:

Function.method('inherits', function (Parent) {
this.prototype = new Parent();
return this;
});

Obie te metody zwracajñ

this

, wiöc moĔemy je wykorzystaè przy äñczeniu wywoäaþ. MoĔe-

my teraz utworzyè nasz obiekt

Cat

za pomocñ jednej instrukcji

1

:

var Cat = function (name) {
this.name = name;
this.saying = 'miau';
}.
inherits(Mammal).
method('purr', function (n) {
var i, s = '';
for (i = 0; i < n; i += 1) {
if (s) {
s += '-';
}
s += 'r';
}
return s;
}).
method('get_name', function () {
return this.says() + ' ' + this.name + ' ' + this.says();
});

Dziöki ukryciu caäego mechanizmu operujñcego na obiekcie

prototype

, ten kod wyglñda

nieco mniej obco. Ale czy naprawdö coĈ ulepszyliĈmy? Mamy teraz funkcje konstruktorów
przypominajñce klasy, ale pod tñ powierzchniñ wciñĔ moĔemy siö natknñè na nieprzewidziane
zachowanie. Nie mamy prywatnego dostöpu — wszystkie wäaĈciwoĈci sñ publiczne. Nie mamy
moĔliwoĈci wywoäywania nieprzesäoniötych wersji metod obiektów nadrzödnych z poziomu
obiektów przesäaniajñcych te metody.

Co gorsza, istnieje pewne ryzyko zwiñzane z uĔyciem funkcji konstruktorów. JeĈli zapomni-
my uĔyè säowa

new

przy wywoäywaniu konstruktora,

this

nie bödzie powiñzane z nowym

1

Kod ten w celu poprawnego nadpisania metody

get_name

wymaga uĔycia implementacji metody

method

podanej na koþcu rozdziaäu 1, a nie jej modyfikacji warunkowej pokazanej na koþcu podrozdziaäu „Rozsze-
rzanie typów” w rozdziale 4. — przyp. täum.

background image

56

_

Rozdzia

ĥ 5. Dziedziczenie

obiektem, lecz z obiektem globalnym. Zamiast wiöc dodaè wäaĈciwoĈci do nowego obiektu, za-
Ĉmiecimy nimi globalnñ przestrzeþ nazw. To bardzo niebezpieczna moĔliwoĈè, tym bardziej,
Ĕe nie otrzymamy Ĕadnego ostrzeĔenia ani podczas kompilacji, ani podczas wykonania kodu.

Jest to powaĔny bäñd projektowy jözyka. Aby sobie jakoĈ z nim radziè, istnieje konwencja na-
kazujñca nadawanie wszystkim funkcjom peäniñcym rolö konstruktorów (i Ĕadnym innym)
nazw zaczynajñcych siö od wielkich liter. To pozwala przynajmniej mieè nadziejö, Ĕe analiza
kodu pozwoli wyäapaè wszystkie brakujñce zastosowania

new

. Lepszñ alternatywñ jest jednak

nie uĔywanie w ogóle säowa

new

.

Pseudoklasyczna forma dziedziczenia pozwala poczuè siö wygodniej programistom niezna-
jñcym dobrze JavaScriptu, ale równoczeĈnie ukrywa ona prawdziwñ naturö tego jözyka. No-
tacja inspirowana podejĈciem klasycznym moĔe zachöcaè do tworzenia przesadnie gäöbokich
i skomplikowanych hierarchii. WiökszoĈè takich skomplikowanych hierarchii klas spowodo-
wana jest ograniczeniami statycznej kontroli typów. JavaScript nie ma takich ograniczeþ. W jö-
zykach klasycznych dziedziczenie klas jest jedynñ formñ wielokrotnego wykorzystania kodu.
JavaScript ma duĔo szersze moĔliwoĈci.

Okre

ļlenia obiektów

Czasami zdarza siö, Ĕe konstruktor pobiera bardzo duĔñ liczbö parametrów. MoĔe to byè
käopotliwe, bo na przykäad utrudnia zapamiötanie kolejnoĈè argumentów. W takich wypad-
kach lepszym rozwiñzaniem moĔe byè napisanie konstruktora, który pobiera pojedyncze
okreĈlenie obiektu (ang. object specifier). OkreĈlenie takie zawiera specyfikacjö obiektu, który
ma byè skonstruowany. Tak wiöc, zamiast takiego wywoäania funkcji:

var myObject = maker(f, l, m, c, s);

moĔemy napisaè:

var myObject = maker({
first: f,
last: l,
state: s,
city: c
});

Argumenty mogñ byè teraz wymienione w dowolnej kolejnoĈci, mogñ byè pominiöte, jeĈli
konstruktor jest w stanie przypisaè im wartoĈci domyĈlne, a caäy kod jest äatwiejszy w czytaniu.

PodejĈcie to moĔe mieè dodatkowe zalety przy korzystaniu z formatu JSON (patrz dodatek E).
Tekst formatu JSON jest w stanie opisaè jedynie dane, ale czasami dane reprezentujñ jakiĈ
obiekt i wygodnie byäoby powiñzaè dane z jego metodami. Okazuje siö to banalne, gdy kon-
struktor pobiera okreĈlenie obiektu, poniewaĔ moĔemy po prostu przesäaè obiekt JSON do
konstruktora, który z kolei zwróci w peäni utworzony obiekt.

Dziedziczenie prototypowe

W wypadku podejĈcia czysto prototypowego, nie uĔywamy w ogóle klas. Skupiamy siö wy-
äñcznie na obiektach. Dziedziczenie prototypowe jest koncepcyjnie prostsze od klasycznego:
nowy obiekt moĔe dziedziczyè wäaĈciwoĈci starego obiektu. Jest to moĔe mniej powszechne
podejĈcie, ale jest za to bardzo äatwe do zrozumienia. Punktem wyjĈcia jest utworzenie jakiegoĈ

background image

Dziedziczenie prototypowe

_

57

poĔytecznego obiektu. W nastöpnym kroku moĔemy utworzyè wiele obiektów podobnych
do niego. Proces klasyfikacji polegajñcy na rozbiciu aplikacji na zbiór zagnieĔdĔonych klas
abstrakcyjnych moĔe byè caäkowicie pominiöty.

Zacznijmy wiöc od utworzenia takiego poĔytecznego obiektu, uĔywajñc literaäu obiektowego:

var myMammal = {
name : "Mój ssak",
get_name : function () {
return this.name;
},
says : function () {
return this.saying || '';
}
};

Majñc obiekt taki jak ten, moĔemy utworzyè wiöcej instancji korzystajñc z funkcji

Ob-

ject.beget

z rozdziaäu 3. Nastöpnie moĔemy je dostosowaè do naszych potrzeb:

var myCat = Object.beget(myMammal);
myCat.name = 'Kicia';
myCat.saying = 'miau';
myCat.purr = function (n) {
var i, s = '';
for (i = 0; i < n; i += 1) {
if (s) {
s += '-';
}
s += 'r';
}
return s;
};
myCat.get_name = function () {
return this.says() + ' ' + this.name + ' ' + this.says();
};

Jest to dziedziczenie róĔnicowe. Zdefiniowanie nowego obiektu polega na okreĈleniu róĔnic
miödzy nim a obiektem, z którego zostaä utworzony.

Czasami wygodnie jest, gdy struktura danych dziedziczy z innej struktury. Oto przykäad:
przypuĈèmy, Ĕe analizujemy kod jözyka takiego jak Java lub T

E

X, w którym para nawiasów

oznacza zasiög. Zmienne zdefiniowane w ramach zasiögu nie sñ widoczne poza nim. W pewnym
sensie wewnötrzny zasiög dziedziczy po zewnötrznym. Obiekty JavaScriptu dobrze siö na-
dajñ do reprezentacji takiej zaleĔnoĈci. Funkcja

block

wywoäywana jest, kiedy napotkany zo-

staje lewy nawias klamrowy. Funkcja

parse

bödzie pobieraè symbole z zasiögu oraz doda-

waè nowo napotkane:

var block = function () {

// Zapami

Ċtujemy dotychczasowy zasiĊg. Tworzymy nowy zasiĊg,

// który b

Ċdzie zawieraá wszystko to, co dotychczasowy.

var oldScope = scope;
scope = Object.beget(scope);

// Przechodz

ąc nad lewym nawiasem klamrowym wchodzimy do nowego zasiĊgu.

advance('{');

// Analizujemy tekst, u

Īywając nowego zasiĊgu.

parse(scope);

background image

58

_

Rozdzia

ĥ 5. Dziedziczenie

// Przechodz

ąc nad prawym nawiasem klamrowym wychodzimy z zasiĊgu

// i przywracamy stary zasi

Ċg.

advance('}');
scope = oldScope;
};

Dziedziczenie funkcyjne

Przedstawione dotñd wzorce dziedziczenia majñ pewien säaby punkt: brak prywatnoĈci. Wszyst-
kie wäaĈciwoĈci obiektów sñ widoczne. Brakuje zmiennych prywatnych oraz prywatnych me-
tod. Czasami nie ma to wiökszego znaczenia, ale czasami moĔe mieè znaczenie ogromne.
Zniechöceni tym faktem niektórzy niedoinformowani programiĈci ukuli zasadö uĔywania
zmiennych niby-prywatnych. Majñc wäaĈciwoĈè, którñ chcieli uczyniè prywatnñ, nadawali jej
dziwnie wyglñdajñcñ nazwö, majñc nadziejö, Ĕe inni uĔytkownicy ich kodu bödñ udawaè, Ĕe
nie widzñ nazw dziwnie wyglñdajñcych. Na szczöĈcie istnieje duĔo lepsza alternatywa oparta
o omawiany wczeĈniej wzorzec moduäu.

Zaczynamy od napisania funkcji, która bödzie wytwarzaè obiekty. Dajemy jej nazwö zaczy-
najñcñ siö od maäej litery, poniewaĔ nie bödzie ona wymagaè uĔycia säowa

new

. Dziaäanie

funkcji skäada siö z czterech kroków:

x

Funkcja tworzy nowy obiekt. Jest na to wiele sposobów: uĔycie literaäu obiektowego,
wywoäanie funkcji konstruktora ze säowem

new

, uĔycie metody

Object.beget

do utwo-

rzenia nowego obiektu na podstawie istniejñcego, wreszcie wywoäanie dowolnej innej
funkcji zwracajñcej obiekt.

x

Opcjonalnie funkcja deklaruje zmienne i metody prywatne. Sñ to zwykäe zmienne (

var

)

funkcji.

x

Nastöpnie funkcja rozszerza nowo utworzony obiekt o metody. Metody te majñ uprzy-
wilejowany dostöp do parametrów i zmiennych zdefiniowanych w poprzednim kroku.

x

Na koniec nowy obiekt jest zwracany.

Oto szablon pseudokodu do tworzenia konstruktora funkcyjnego (pogrubiony tekst dodano
dla podkreĈlenia niektórych fragmentów):

var constructor = function (spec, my) {
vat that, inne prywatne zmienne instancyjne;
my = my || {};

// tu dodajemy do obiektu my zmienne i funkcje wspóádzielone

that = nowy obiekt;

// tu dodajemy do obiektu that metody uprzywilejowane

return that;
}

Obiekt

spec

zawiera wszystkie informacje niezbödne konstruktorowi do utworzenia instancji.

ZawartoĈè obiektu

spec

moĔe byè skopiowana do zmiennych prywatnych lub przetworzona

przez inne funkcje, bñdĒ teĔ metody mogñ pobieraè informacje z tego obiektu w razie potrzeby.
(MoĔna teĔ to uproĈciè zastöpujñc

spec

pojedynczñ wartoĈciñ. Jest to wygodne, gdy tworzony

obiekt nie wymaga peänego obiektu

spec

.)

background image

Dziedziczenie funkcyjne

_

59

Obiekt

my

säuĔy przechowywaniu chronionych danych, które mogñ byè wspóädzielone z kon-

struktorami w ramach äaþcucha dziedziczenia. UĔycie tego obiektu jest opcjonalne. JeĈli nie jest
on przekazany do funkcji, tworzony jest pusty.

Nastöpnie deklarujemy prywatne zmienne instancyjne oraz prywatne metody obiektu. Odby-
wa siö to poprzez zwykäe zadeklarowanie zmiennych. Zmienne i funkcje wewnötrzne utwo-
rzone wewnñtrz konstruktora stajñ siö zmiennymi i funkcjami prywatnymi instancji. Funkcje
wewnötrzne majñ dostöp do

spec

,

my

,

that

i innych zmiennych prywatnych.

Nastöpnie dodajemy wspóädzielone dane chronione do obiektu

my

. Wykonuje siö to poprzez

przypisanie:

my.member = value;

Teraz tworzymy nowy obiekt i przypisujemy go do

that

. Jest wiele sposobów utworzenia

obiektu. MoĔemy uĔyè literaäu obiektowego. MoĔemy wywoäaè pseudoklasyczny konstruktor,
uĔywajñc operatora

new

. MoĔemy wywoäaè metodö

Object.beget

na prototypie obiektu.

Wreszcie moĔemy skorzystaè z dowolnego innego konstruktora funkcyjnego, przekazujñc mu
obiekt

spec

(najczöĈciej ten sam, który zostaä przekazany do tego konstruktora) oraz obiekt

my

.

Obiekt

my

pozwala na wspóädzielenie informacji z innymi konstruktorami. Inne konstruktory

mogñ równieĔ umieszczaè swoje wäasne chronione dane w tym obiekcie, w celu wspóädzie-
lenia ich z naszych konstruktorem.

Nastöpnie rozszerzamy

that

, dodajñc metody uprzywilejowane stanowiñce interfejs obiektu.

MoĔemy przypisywaè nowe funkcje bezpoĈrednio do

that

. Lub teĔ, w bardziej bezpieczny spo-

sób, najpierw zdefiniowaè funkcje jako metody prywatne, a nastöpnie przypisaè je do

that

:

var methodical = function () {
...
};
that.methodical = methodical;

Zaletñ definiowania metod w dwóch etapach jest to, Ĕe jeĈli inne metody bödñ chciaäy wywo-
äywaè

methodical

, bödñ mogäy zrobiè to przez wywoäanie

methodical()

zamiast

that.metho

´dical()

. JeĈli instancja zostanie uszkodzona lub zmanipulowana, tak Ĕe metoda

that.

´methodical

zostanie zastñpiona innñ, wówczas funkcje wywoäujñce funkcjö

methodical

bödñ nadal dziaäaè poprawnie, poniewaĔ funkcja prywatna

methodical

pozostanie nienaru-

szona mimo modyfikacji obiektu.

Na koniec zwracamy

that

.

Zastosujmy ten wzorzec do naszego przykäadu z ssakami. Nie potrzebujemy tutaj zmiennej

my

,

wiöc po prostu jñ opuĈcimy, ale za to przyda nam siö obiekt

spec

.

WäaĈciwoĈci

name

i

saying

sñ teraz caäkowicie prywatne. Dostöp do nich jest moĔliwy tylko

dziöki uprzywilejowanym metodom

get_name

i

says

:

var mammal = function (spec) {
var that = {};

that.get_name = function () {
return spec.name;
};

that.says = function () {
return spec.saying || '';
};

background image

Czytaj dalej...

60

_

Rozdzia

ĥ 5. Dziedziczenie

return that;
};

var myMammal = mammal({name: 'Mój ssak'});

W podejĈciu pseudoklasycznym konstruktor

Cat

musiaä duplikowaè pracö wykonywanñ przez

konstruktor

Mammal

. We wzorcu funkcyjnym nie jest to konieczne, poniewaĔ konstruktor

Cat

wywoäa konstruktor

Mammal

, który sam wykona swoje zadanie. Konstruktor

Cat

zajmuje siö

tylko róĔnicami miödzy nimi:

var cat = function (spec) {
spec.saying = spec.saying || 'miau';
var that = mammal(spec);
that.purr = function (n) {
var i, s = '';
for (i = 0; i < n; i += 1) {
if (s) {
s += '-';
}
s += 'r';
}
return s;
};
that.get_name = function () {
return that.says() + ' ' + spec.name + ' ' + that.says();
};
return that;
};

var myCat = cat({name: 'Kicia'});

Wzorzec funkcyjny umoĔliwia nam równieĔ wywoäywanie metod z obiektów nadrzödnych.
Napiszmy metodö

superior

, która pobieraè bödzie nazwö metody i zwracaè funkcjö wywo-

äujñcñ tö metodö. Funkcja ta bödzie wywoäywaè oryginalnñ metodö, nawet gdy wäaĈciwoĈè
zostaäa zmieniona przez obiekt potomny:

Object.method('superior', function (name) {
var that = this,
method = that[name];
return function () {
return method.apply(that, arguments);
};
});

Wypróbujmy jñ na obiekcie

coolcat

, który jest podobny do obiektu

cat

, ale ma nieco ciekaw-

szñ metodö

get_name

, która wywoäuje nieprzesäoniötñ wersjö metody z obiektu nadrzödnego.

Wymaga to tylko niewielkich przygotowaþ. Zadeklarujemy zmiennñ

super_get_name

i przypi-

szemy jej wynik wywoäania metody

superior

:

var coolcat = function (spec) {
var that = cat(spec),
super_get_name = that.superior('get_name');
that.get_name = function (n) {
return 'Teraz ' + super_get_name() + ' w nowej, lepszej wersji';
};
return that;
};

var myCoolCat = coolcat({name: 'Kocur'});
var name = myCoolCat.get_name(); // 'Teraz miau Kocur miau w nowej, lepszej wersji'


Wyszukiwarka

Podobne podstrony:
informatyka javascript aplikacje www alex maccaw ebook
JavaScript mocne strony
informatyka javascript programowanie obiektowe stoyan stefanov ebook
informatyka php nuke tworzenie witryn www douglas paterson ebook
informatyka javascript wprowadzenie shelley powers ebook
informatyka javascript wzorce stoyan stefanov ebook
informatyka adobe air dla programistow javascript leksykon kieszonkowy mike chambers ebook
Informacje na temat strony internetowej Stwórców Skrzydeł
moje mocne strony
słabe i mocne strony funkcjonowania firmy Kross, nauka, Adam Stabryła, Zarządzanie strategiczne w te
Moje mocne strony- do pr.zawodowej, scenariusze
MOCNE STRONY
potencjalne mocne strony Z56LYYIVM6ZOJM5T46S7HDJ4V2XNEACSPUOK2DA
Systemy informacyjne w zarzadzaniu [24 strony], FSI
MOCNE STRONY DDA, psychologia

więcej podobnych podstron