chevron-left chevron-right

[JS] Obiektowe podejście do JavaScript. Jak stworzyć klasę?

Tematem dzisiejszego artykułu będzie tworzenie klas za pomocą języka JavaScript. Dla wielu może to brzmieć dziwnie z racji popularności biblioteki jQuery, gdzie używa się jej w sposób zupełnie bezklasowy.
Należy jednak uściślić, że w JS klasami są funkcje będące obiektami. Brzmi skomplikowanie?
Po przeczytaniu tego wpisu mam nadzieję, że wszystko będzie nieco jaśniejsze.

Klasy w JS można definiować na kilka różnych sposobów. Każdy z nich ma swoje zalety i wady.

Klasa jako funkcja

Jest to najpopularniejszy sposób tworzenia klas, zbliżony wyglądem do tradycyjnych klas w językach obiektowych takich jak: PHP czy C++. Tworzenie klas jako funkcji można rozdzielić na 3 podejścia:

  1. Metody klasy są utworzone wewnątrz klasy

    Jest to bardzo popularny sposób definiowania klas. Dzięki temu uzyskujemy strukturę kodu charakterystyczną dla klasycznych klas w programowaniu obiektowym. Nowy obiekt klasy jest wywoływany za pomocą operatora new.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    function Osoba(imie,wiek) {
    	this.imie = imie;
    	this.wiek = wiek;
    	this.pokazInfo = function() {
    		window.alert(this.imie+' ma '+this.wiek+' lat');
    	}
    }
     
    var jacek = new Osoba('Jacek',39);
    jacek.pokazInfo();
  2. Metody klasy są przypisane do zewnętrznych funkcji

    To podejście pozwala na zdefiniowanie funkcji na zewnątrz klasy. Dzięki temu różne klasy mogą korzystać z tych samych metod jeśli zaistnieje taka potrzeba. Jest to przykład antywzorca.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    function Osoba(imie,wiek) {
    	this.imie = imie;
    	this.wiek = wiek;
    	this.pokazInfo = getItemInfo;
    }
     
    function getItemInfo() {
    	window.alert(this.imie+' ma '+this.wiek+' lat');
    }
  3. Metody klasy są utworzone w prototypie klasy

    Przykład pierwszy pokazał, że można tworzyć klasy ze zdefiniowanymi metodami wewnątrz ciała obiektu. Jest to rozwiązanie wygodne, ale dość kosztowne jeśli chodzi o zarządzanie pamięcią. Dlatego pewnego rodzaju wyjściem może być korzystanie z prototypów klas.

    1
    2
    3
    4
    5
    6
    7
    8
    
    function Osoba(imie,wiek) {
    	this.imie = imie;
    	this.wiek = wiek;
    }
     
    Osoba.prototype.pokazInfo = function() {
    	window.alert(this.imie+' ma '+this.wiek+' lat');
    }

Klasa jako obiekt typu singleton

W tym przypadku tworzymy obiekt Javascript bezpośrednio. Funkcjonalność takiej klasy będzie identyczna z tymi zaprezentowanymi wcześniej. Jedyne co się zmieni to fakt, że klasa staje się też obiektem na którym można dokonywać działań i nie można tworzyć wielu obiektów z tej samej klasy. Dlatego jest mowa o wzorcu singleton. Który dba o to, aby nie było więcej niż jeden obiekt danej klasy jednocześnie.

1
2
3
4
5
6
7
8
9
10
var osoba = {
	imie: 'Jacek',
	wiek: 39,
	pokazInfo: function() {
		window.alert(this.imie+' ma '+this.wiek+' lat');
	}
}
 
osoba.imie = 'Placek';
osoba.pokazInfo();

Podsumowanie

Dzięki stosowaniu klas uzyskujemy odpowiednią przejrzystość kodu, co gwarantuje, że wszystkie wystąpienia klas będą się zachowywały podobnie niezależnie od zmian w metodach klasy. Dodając do tego możliwości biblioteki jQuery i chociażby Canvas API można się pokusić o naprawdę interesujące efekty obiektowego programowania/skryptowania.

Mam nadzieję, że ten artykuł okaże się pomocny i pozwoli Ci rozwinąć swoje umiejętności w projektowaniu aplikacji internetowych.

  • Od kiedy funkcja jest zbliżona do metody, pola i obiektu? Sory ale JS nie jest obiektowe i takie próby udowadniania nie mają racji bytu. Zajrzyj do manuala chociażby PHP i przepisz te wszystkie możliwości na JS to wtedy uwierzę!

  • Piotr Nalepa

    być może lepszy określeniem byłoby „jak klasa”, ale generalnie treść artykułu oddaje sens tworzenia tego typu rzeczy

  • JS potrafi działać jako „programowanie oparte o obiekty”, a nie „programowanie zorientowane obiektowo”. Rzeczy takie jak przeciążanie operatorów, interfejsy – są może i niepotrzebne, bo PHP jakoś bez tego daje radę, ale bez takich rzeczy jak prawdziwe dziedziczenie, hermetyzacja słabo da się programować na większą skalę… Rozwiązania serwerowe typu Node.JS o tyle mnie fascynują, że twórcy wybrali sobie chyba najmniej wygodny język i starają się tym wbić na rynek programowania serwerowego gdzie większość ma PHP, sporą część .NET, a kilka procent RoR, Python, Perl i reszta eksperymentów…

  • Henryk

    Widzę po komentarzach, że znowu trawiłem na grono przemadrzalych krytykow, dosc czeste w polskim IT.
    JS jest obiektowa i tyle i można pisać aplikacje zorientowane obiektowo, ale na pewno nie ma wszystkich mechanizmów takich jak inne języki, bo JS ma swoje przeznaczenie, a inne jezyki maja swoje przeznaczenie. A przy okazji uwaga do kolegi ‚proces’ interfejsy istnieją w PHP od wersji 5, czyli kilka lat, a przeciążanie można bez problemu realizować bo jest to tego narzędzie func_get_args. W objective-C nie ma interface, ale są protokoły ( czyli to w sumie to samo ale nazwa inna ) ,a to jeden z bardzo obiektowych języków. to ze w języku nie ma slowa kluczowego class albo interface to nie znaczy ze to nie jest jezyk obiektowy, ale ze nie ma w nim klas lub interface. Skoro w JS jest operator ‚new’ i mozna sworzyc kilka obiektow tej samej klasy (wzorca, prototypu – jak zwal tak zwal) to oznacza ze w JS sa klasy i sa obiekty. rozne sa skladnie jezykow i rozny zakres ich obiektowosci. PHP4 z tego co pamietam nie mial operatorow zasiegu ‚private,protected,public’ bo wszystko bylo public, a tez byl obiektowy i w PHP4 powstalo wiele pierwszych obiektowych fajnych narzedzi ( phpmyadmin z tego co pamietam ) Uwazam ze artykul jest bardzo fajny bo w kilku akapitach oddaje sedno sprawy a wszystkich przemadrzalych krytykow pozdrawiam

  • Bardzo ciekawy artykuł. Ciekawie byłoby też przedyskutować, jak używać prototypów w JavaScript, chcąc pisać w stylu, jaki był intencją autorów języka …

  • Piotr Nalepa

    Myślę, że taka dyskusja byłaby ciekawa i dałaby interesujące światło na stan użytkowania języka JS w dzisiejszych czasach.

  • Łukasz

    to ostatnie to raczej zwykły globalny obiekt, a nie singleton 😉

    „To podejście pozwala na zdefiniowanie funkcji na zewnątrz klasy. Dzięki temu różne klasy mogą korzystać z tych samych metod jeśli zaistnieje taka potrzeba. Jest to przykład antywzorca.”

    A tego nie rozumiem. Czemu to miałby być antywzorzec? W JavaScript często wygodnie jest „podczepić” metodę do obiektu. Np. przy obsłudze wszelakich zdarzeń, callbacków itp. Nawet w sumie często się podczepia te metody doraźnie za pomocą wywołania funkcja.call albo funkcja.apply…

    PS. zabawne jest widzieć, jak ktoś próbuje podminować obiektowość JS używając za konrprzykład język PHP, który specjalnie obiektowy wcale nie jest (prędzej Java, Python, C++… ).

  • aa

    Artykuł napisany na odpiertol. Każdy ze sposobów tworzenia klas ciągnie za sobą poważne konsekwencje, np. to, że tworzymy metody wewnątrz klasy powoduje, że przy tworzeniu każdej instancji w pamięci metoda będzie od nowa tworzona. Można zastosować warunek .if (obj_initialize == undefined ) aby to obejść, ale to osobny temat.
    Są przeróżne wzorce: konstruktor-prototyp, dynamiczny konstruktor itd. itp.
    Temat rzeka ujęto tu w dwóch zdaniach. Zaśmiecanie neta, nic więcej. Do tego błędy rzeczowe.