Warning: file_get_contents(http://graph.facebook.com/http://youthcoders.net/index.php): failed to open stream: HTTP request failed! HTTP/1.0 403 Forbidden in /var/www/old-yc/plugins/content/addthis.php on line 38
Tworzenie obiektów JS z prototypu Drukuj
Ocena użytkowników: / 1
SłabyŚwietny 
Wpisany przez Patryk yarpo Jar   
wtorek, 15 czerwca 2010 23:30

Jest wiele sposobów na tworzenie obiektów w JS. Każdy ma jakieś wady i zalety. Należy wybrać taki, który nam się najbardziej podoba, i który akurat przy konkretnym zastosowaniu jest najwygodniejszy. W tym artykule pokażę, jak tworzyć w JS obiekty z wykorzystaniem mechanizmu prototypowania.

 

Język obiektowy bez klas

No tak! Ledwo zacząłeś widzieć korzyści płynące z tworzenia klas i operowaniu na obiektach, a tu Ci ktoś mówi, że nie ma klas w JS:). Ano nie ma. Są za to prototypy. I tak naprawdę to zasada jest bardzo podobna. Zobaczmy kod, bo tak zawsze łatwiej:

 

1.function MyObject() { } // 1
2.MyObject.prototype.sayHi = function() // 2
3.{
4.    alert("Witaj świecie"); // 3
5.};
6. 
7.var oMyObj = new MyObject(); // 4
8.oMyObj.sayHi() // 5
  1. Tworzymy pustą funkcję. Jako,  że w JS wszystko jest obiektem, to funkcja też jest obiektem. Nazwiemy takie "cuś" konstruktorem.
  2. Do prototypu obiektu o nazwie MyObject dodajemy metodę `sayHi()', ...
  3. ... która po prostu wyświetla "witaj świecie"
  4. Tworzymy nowy obiekt. Zauważ, że używamy słówka (fachowo - operatora) `new'. W tym momencie do zmiennej oMyObj zostaje przypisany obiekt stworzony wg wytycznych zawartych w prototypie MyObject. Czyli posiada pusty konstruktor (patrz [1]) oraz metodę `sayHi()' [2]. Konstruktor zostaje wywoływany przy tworzeniu obiektu. Metodę, możemy wyołać sami, co też robimy w [5].
  5. Wywołujemy metodę sayHi().

 

Po wykonaniu tego skryptu w przeglądarce powinnien pojawić się alert z napisem "witaj świecie".

 

Właściwości prototypu obiektu

Obiekt może mieć właściwości i metody (w uproszczeniu: zmienne = właściwości, funkcje = metody). W językach posiadających klasy właściwości są przypisywane do klasy. W JS można to zrobić na wiele sposobów (porównaj artykuły o dodawaniu metod do istniejących obiektów oraz o rozszerzaniu prototypu obiektu). Stwórzmy zatem taką właściwość, którą będą posiadać wszystkie obiekty tworzone wg prototypu obiektu MyObject:

 

1.function MyObject() {}
2.MyObject.prototype.sentence = 'Witaj świecie'; // 1
3.MyObject.prototype.sayHi = function()
4.{
5.    alert(this.sentence); // 2
6.};
7.var oMyObj = new MyObject();
8.oMyObj.sayHi();

 

Nic się nie zmieniło w wyniku, porównując z poprzenim przypadkiem. Jednak w kodzie widzimy dwie zmiamy:

  1. Do prototypu obiektu MyObject dodajemy właściwość `sentence' i przypisujemy jej wartość "Witaj świecie".
  2. W alercie nie wstawiamy już na sztywno ciągu znaków, a odnosimy się do właściwości `sentence'. Używamy tu operator `this'. Można to przetłumaczyć tak: "jestem obiektem stworzonym wg prototypu `MyObject'. `this' to ja sam. Poszukaj zatem mojej właściwości o nazwie `sentece'". W językach, w których są klasy [np. PHP] także występuje operator $this.

Skoro już wyrzuciliśmy powitalny tekst do zmiennej, to spróbujmy go zmienić :). Najlepiej za pomocą konstruktora. Co on taki pusty ma być :)

 

Sparametryzowanie konstruktora

01.function MyObject( msg ) // 1
02.{
03.    if (msg) // 2
04.    {
05.        this.sentence = msg; // 3
06.    }
07.}
08. 
09.MyObject.prototype.sentence = 'Witaj świecie'; // 4
10.MyObject.prototype.sayHi = function()
11.{
12.    alert(this.sentence); // 5
13.};
14. 
15.var oMyObj_one = new MyObject(); // 6
16.var oMyObj_two = new MyObject("A ja nie będę taki jak inni"); // 7
17.var oMyObj_three = new MyObject(); // 6
18. 
19.oMyObj_three.sentence = 'Za to ja to już w ogóle jest krejzol'; // 8
20.oMyObj_one.sayHi(); // 9
21.oMyObj_two.sayHi(); // 9
22.oMyObj_three.sayHi(); // 9

 

Się nam kodu narobiło :). Spokojnie, nie jest tak źle jakby się mogło wydawać. Po kolei:

  1. Nasz konstruktor posiada teraz parametr. Czyli tworząc nowy obiekt możemy podać mu jakąś wartość.
  2. Ten warunek można przetłumaczyć na: "Jeśli `msg' ma jakąś wartość". Czyli jeśli wywołamy ten konstrukotr bez parametrów (patrz [6]) to nie wejdzie do tego ifa. Czytaj więcej o fasy values.
  3. Jeśli podaliśmy jakiś ciąg jako parametr (patrz [7]) to do właściwości `sentence' tego konkretnego obiektu zostanie przypisana nowa wartość i ...
  4. ... nadpisze ona domyślną wartość pola `sentece'.
  5. W metodzie `sayHi()' wyświetlone zosatnie zdanie podane do konstruktora, lub domyślna wartość jeśli do konstruktora nie podano zdania.
  6. Tworzymy obiekty bez parametrów. Czyli w polach `sentece' tych obiektów występuje wartość domyślna.
  7. Tworzymy obiekt podając konkretną wartość do konstruktora. W tym obiekcie w polu `sentence' jest wartość "A ja nie będę taki jak inni".
  8. Nadpisujemy "ręcznie" wartość właściwości `sentence'.
  9. Wywołujemy metodę `sayHi()' wszystkich trzech obiektów.

 

Ja rzadko używam tego sposobu tworzenia obiektów w JS, mimo, że jest on najbardziej klasopodobny. Staram się raczej wykorzystywać wzorzec modułu.

 

Pełen kod z dodatkowym bonusem:

Jak sądzisz, co zrobi kod z framentu oznacznonego BONUS? 

 

001.<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
002. 
003.    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pl" lang="pl">
004. 
005.    <head>
006. 
007.        <title>Tworzenie obiektów z wykorzystaniem prototypów</title>
008. 
009.        <meta http-equiv="content-type" content="text/html;charset=utf-8" />
010. 
011.        <script type="text/javascript">
012. 
013.    (function() {
014. 
015.        function MyObject() {}
016. 
017.        MyObject.prototype.sayHi = function()
018. 
019.        {
020. 
021.            alert("Witaj świecie");
022. 
023.        };
024. 
025.        var oMyObj = new MyObject();
026. 
027.        oMyObj.sayHi();
028. 
029.    })();
030. 
031.      
032. 
033.    (function() {
034. 
035.      
036. 
037.        function MyObject() {}
038. 
039.        MyObject.prototype.sentence = 'Witaj świecie';
040. 
041.        MyObject.prototype.sayHi = function()
042. 
043.        {
044. 
045.            alert(this.sentence);
046. 
047.        };
048. 
049.        var oMyObj = new MyObject();
050. 
051.        oMyObj.sayHi();
052. 
053.    })();
054. 
055.      
056. 
057.    (function() {
058. 
059.        function MyObject( msg )
060. 
061.        {
062. 
063.            if (msg)
064. 
065.            {
066. 
067.                this.sentence = msg;
068. 
069.            }
070. 
071.        }
072. 
073.      
074. 
075.        MyObject.prototype.sentence = 'Witaj świecie';
076. 
077.      
078. 
079.        MyObject.prototype.sayHi = function()
080. 
081.        {
082. 
083.            alert(this.sentence);
084. 
085.        };
086. 
087.      
088. 
089.        var oMyObj_one = new MyObject();
090. 
091.        var oMyObj_two = new MyObject("A ja nie będę taki jak inni");
092. 
093.        var oMyObj_three = new MyObject();
094. 
095.        oMyObj_three.sentence = 'Za to ja to już w ogóle jest krejzol';
096. 
097.        oMyObj_one.sayHi();
098. 
099.        oMyObj_two.sayHi();
100. 
101.        oMyObj_three.sayHi();
102. 
103.    })();
104. 
105.     /* BONUS  */
106. 
107.    (function() {
108. 
109.        function MyObject( msg )
110. 
111.        {
112. 
113.            if (msg)
114. 
115.            {
116. 
117.                this.sentence = msg;
118. 
119.            }
120. 
121.        }
122. 
123.        MyObject.prototype.sentence = 'Witaj świecie';
124. 
125.      
126. 
127.        MyObject.prototype.sayHi = function()
128. 
129.        {
130. 
131.            alert(MyObject.prototype.sentence);
132. 
133.        };
134. 
135.      
136. 
137.        var oMyObj_one = new MyObject();
138. 
139.        var oMyObj_two = new MyObject("A ja nie będę taki jak inni");
140. 
141.        var oMyObj_three = new MyObject();
142. 
143.        oMyObj_three.sentence = 'Za to ja to już w ogóle jest krejzol';
144. 
145.        oMyObj_one.sayHi();
146. 
147.        oMyObj_two.sayHi();
148. 
149.        oMyObj_three.sayHi();
150. 
151.    })();
152. 
153.        </script>
154. 
155.    </head><body></body></html>

 

Jeśli nie rozumiesz o co chodzi z takim kodem:

1.(function() { ... })();

To warto przeczytać artykuł o zasięgu zmiennych w JS. Szczególnie część o "Rozsądnym zastosowaniu".