Programowanie obiektowe. OOP w JavaScript część 2. Podsumowanie.

JavaScript OOP

Poziom zaawansowany

Część 2. podsumowująca na temat OOP w JavaScript. Pokażemy dziś nieco bardziej zaawansowane przykłady.

Techniki OOP w JavaScript – krok dalej

Na dobry początek weźmy pod lupę tablice.

Tablice jako obiekty

Zwykłą tablicę:

var t = new Array("a","b","c");

można zapisać w zwięzłej formie:

var t = ["a","b","c"];

i oczywiście operować podobnie, jak operowaliśmy na innych obiektach.

Przykładowe operacje typowe dla tablic w JS:

tablica.push("x"); // dodanie elementu 

alert(tablica.pop()); // zdjęcie / pobranie 

// kasowanie elementu pod danym indeksem
var index = 0;
delete tablica[indeks];

Tablice asocjacyjne

Twory dobrze znane w PHP, możemy tworzyć w JavaScript w dość przyjemny sposób:

var numbers_object = {
    '0': 'zero', '1': 'jeden', '2': 'dwa',
    '3': 'trzy', '4': 'cztery', '5': 'pięć',
    '6': 'sześć', '7': 'siedem', '8': 'osiem',
    '9': 'dziewięć'
};

alert(numbers_object[7]);

Zarządzanie obiektami

Nie chodzi mi tutaj o to, że będziemy zastępować Garbage Collector, raczej o możliwości jakie mamy, gdy chcemy panować nad naszymi obiektami.

Przykład podstawowy – kasowanie obiektu:

var foo = new Object();

delete foo;

Używając wbudowanego operatora delete, możemy skasować składową (właściwość) obiektu, element tablicy, czy też właśnie cały obiekt.

Fabrykowanie obiektów (OOP factory)

Prosty przykład implementacji fabryki obiektów:

function createCar(sColor, iDoors) {
    var oTempCar = new Object();
    oTempCar.color = sColor;
    oTempCar.doors = iDoors;
    oTempCar.showColor = function () {
        alert(this.color)
    };

    return oTempCar;
}

var oCar1 = createCar("czerwony", 4);
oCar1.showColor();  // wyświetla: "czerwony"

Kopiowanie obiektów

W celu skopiowania obiektu, należy skopiować wszystkie jego pola:

Object.prototype.clone = function() {
    var n = {};
    for (p in this) {
        n[p] = this[p];
    }

    return n;
}

Po raz kolejny: OOP w JavaScript poprzez prototypowanie

JS tworzy obiekty na podstawie prototypów. Każdy nowy obiekt jest kopią wcześniej stworzonego wzoru — prototypu. Prototyp jest umieszczony w polu prototype funkcji.

Poniżej dwa przykłady użycia.

Przykład 1:

// konstruktor dla "klasy" NowaKlasa
var NowaKlasa = function(){}
NowaKlasa.prototype.hello = "hello world!" ;

var k = new NowaKlasa()
alert(k.hello); // wyświetli "hello world!"

Przykład 2:

function Car() {
}

Car.prototype.color = "czerwony";
Car.prototype.doors = 4;
Car.prototype.drivers = new Array("Zenon", "Anna");

Car.prototype.showColor = function () {
    alert(this.color);
};

var oCar1 = new Car();
oCar1.drivers.push("Maciek");
alert(oCar1.drivers); // wyświetla "Zenon, Anna, Maciek"

Podsumowując:
prototyp – odwołanie do „klasy”:

samochod.prototype.kolor = null; // prototyp

natomiast odwołanie do samego obiektu:

mojSam.kolor = "white";

Przyporządkowanie metod odbywa się następująco:

obiekt.metoda = nazwa_funkcji;

Usuwanie właściwości to po prostu:

delete obiekt.kolor;

Kolejne przykłady praktyczne

Jeden obraz wart więcej niż 1000 słów (obiektów typu String)… Dobry przykład może dać więcej niż dobry opis, mam więc nadzieję, że przykłady poniżej spełnią zadanie.


Przykład implementacji stosu

ATD (abstrakcyjny typ danych) stosu implementuje się jako tablicę. JavaScript daje odpowiednie funkcje(push, pop):

var stack = new Array();
stack.push("czerwony");
stack.push("zielony");
alert(stack.toString());  // "czerwony, zielony"

var vItem = stack.pop();
alert(vItem); // "zielony"

alert(stack.toString());  // "czerwony"

Kto implementował choćby własny stos w C, doceni łatwość wykonania tego zadania używając OOP w JavaScript.

A co jeśli dostępne już metody nam nie odpowiadają, tudzież chcielibyśmy napisać je po swojemu. Żaden problem, ponieważ możliwe jest…

… nadpisanie metod:

// nadpisanie metody pop():
Array.method('pop', function (  ) {
    return this.splice(this.length - 1, 1)[0];
});

// nadpisanie metody push():
Array.method('push', function () {
    this.splice.apply(
    this,
    [this.length, 0].concat(
        Array.prototype.slice.apply(arguments)));

    return this.length;
});

Kolejny przykład jest właściwie trywialny, ale użyteczny.

Przykład – obiektowy event handler:

<h1 id="myH1">Nagłówek.</h1>
function eventHandler() {
    alert("Event!");
}

var myH1Object = document.getElementById("myH1");
myH1Object.onclick = eventHandler;

Natomiast poniższy przykład to próbka typowo obiektowego JS.

Przykład – implementacja słownika:

function uniwersalnyTlumacz() {
    this.copyright = "Jan Kowalski 2010";
}

function uniwersalnyLicznik() {
    this.Count = count;
    
    var numbers = {
        "en": "one, two, three",
        "fr": "un, deux, trois",
        "de": "eins, zwei, drei"
    };

    function count(language) {
        if (numbers[language]) {
            window.alert(numbers[language] +
            " [" + this.copyright + "]");
        } else {
            alert("Nieznany język");
        }
    }
}

uniwersalnyLicznik.prototype = new uniwersalnyTlumacz();

var ul = new uniwersalnyLicznik();
ul.Count("de");

Podsumowanie

I to już wszystko. Opisaliśmy kluczowe informacje potrzebne do pracy z OOP w JavaScript, przedstawiliśmy różne przykłady kodów.

Zanim przejdziemy do jeszcze ciekawszych rzeczy, jak AJAX i framework’i JavaScript, weźmiemy pod lupę obiekty Number i Math, oraz wykonywanie obliczeń w JS.

Zajmiemy się tym w następnym artykule. Dobrze będzie mieć go pod ręką w przyszłości, kiedy na przykład weźmiemy na warsztat programowanie gier. Z pewnością nie zabraknie wtedy ani matematyki, ani OOP w JavaScript.

Programista WWW i aplikacji mobilnych z wieloletnim doświadczeniem, początkujący bloger. Pasjonat programowania, nowych technologii, e-commerce, a także sportu i motoryzacji.

Twitter LinkedIn Google+ Skype Xing 

Podaj dalej: Share on Facebook0Tweet about this on TwitterShare on Google+2Share on LinkedIn1Share on Tumblr0Digg thisEmail this to someonePin on Pinterest1
Możesz skomentować leave a response, lub podać trackback z własnej strony.
  • Nice.

    Widzę że piszesz i używasz w praktyce prototype.
    A ja, tylko jako ciekawostkę wspomnę o __proto__ …

    Ogólnie prototype jest dobrze znane, __proto__ nie koniecznie

    Patrząc na dyskusje na stackoverflow potrafi być zawiły 😀

    Ale podlinkuję cynki dla, jak to mówisz „dociekliwych”:

    http://stackoverflow.com/search?q=+__proto__

    greetz.js

    • Dzięki

      szczerze mówiąc o __proto__ miałem w brudnopisie mały paragraf, ale postanowiłem przemilczeć 😉

  • W fabryce obiektów [OOP Factory] proponowałbym jednak nie używać:
    var oTempCar = new Object;

    A zamiast tego:
    var oTempCar ={};

    Dlaczego?
    http://www.yarpo.pl/2011/02/16/json-zamiast-konstruktorow/

    Tablice asocjacyjne, to także de facto obiekty 🙂 [co w js, gdzie wszystko jest obiektem, nie dziwi] 🙂

  • Pitagorejczycy: Wszystko jest liczbą.

    JavaScriptowcy: Wszystko jest obiektem.

    🙂