
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.