Oo Javascript

download Oo Javascript

If you can't read please download the document

Transcript of Oo Javascript

OBJECT ORIENTED JAVASCRIPTguida per un mondo migliore

Davide Cerbo
http://jesty.it

Stefano Linguerri
http://www.eljeko.net

Una cattiva impressione

L'unione fa la forza

JAVASCRIPT + PROTOTYPE

Perch usare Prototype

Codice pi breve

Sintassi pi chiara

Gestisce le incompatibilit trai vari browser

Fornisce diverse funzioni e oggetti di utilit

Permette lo sviluppo di Javascript non intrusivo

E' complementare a Script.aculo.us

Qualcosa di utile

$('...') come getDocumentById('...') ma ritorna un Element di Prototype

$$('...') Selettore CSS
$$('.menu #submenu)
ritorna tutti gli elementi che hanno class submenu all'interno di
un elemento che ha id menu

Ajax.request(Url, {...}) Esegue una richiesta AJAX, le graffe conterranno le opzioni della request:
new Ajax.Request(url, {onSuccess: function(transport) {...});
Esistono anche altri metodi come: updater e periodicalUpdater.

Template Permette di definire delle stringe parametrizzabili
var t = new Template('Name: #{name}, surname: #{surname}');
var show = {name: 'Davide', surname: 'Cerbo'};
t.evaluate(show); //return Name: Davide, surname: Cerbo

Observer Permette di osservare gli eventi su un elemento
$('id').observe('click', function(element){...});

Di cosa abbiamo bisogno?

Per considerare JAVASCRIPT un linguaggio Object Oriented abbiamo bisogno di:

Strutture dati complesse

Classi

Interfacce

Polimorfismo

Strutture dati complesse

Hash var h = new Hash();
h.set(key, value);
h.get(key); //return value
h.unset(key);
h.toQueryString() //return key1=v1&key2=v2&...

Enumerable sono liste iterabili con metodi come
each, map, find, select, etc...
$A(...).each(function(e){ alert(e.id); });
$$('...') restituisce un Enumerable

Sono tutte CLOSURE

Questione di classe

Javascript Classico

var Person = Class.create();Person.prototype = { initialize: function(name) { this.name = name; }, say: function(message) { return this.name + ': ' + message; }};var jack = new Person(Jack Maffai);jack.say(Hi Boy);//return Jack Maffai: Hi boy!

Prototype

var Person = Class.create({ initialize: function(name) { this.name = name; }, say: function(message) { return this.name + ': ' + message; }});

var jack = new Person(Jack Maffai);jack.say(Hi Boy);//return Jack Maffai: Hi boy!

Estendiamo

Javascript classico

var Pirate = Class.create();Pirate.prototype = Object.extend(new Person(), { say: function(message) { return this.name + ': ' + message + ', yarr!'; }});

Prototype

var Pirate = Class.create(Person, { say: function($super, message) { return $super(message) + ', yarr!'; }});

new Pirate(Jack Maffai).say(Hi Boy!);//say return: Hi Boy!, yarr!

Interfacce?

Non ci sono e basta!

Accontentiamoci delle classiE ricordiamoci che in Javascript vige la regola:

If it walks like a duck and quacks like a duck, I would call it a duck.

Al volo

var john = new Pirate('Long John');

john.sleep();// -> ERROR: sleep is not a method

Person.addMethods({ sleep: function() { return this.say('ZzZ'); }});

john.sleep();// -> "Long John: ZzZ, yarr!"

Il metodo viene aggiunto a tutte le istanze e le sottoclassi di Pirate

DOMinare con Prototype

Questo approccio deve cambiare il nostro modo di vedere la programmazione Javascript

PROGRAMMAZIONE
FUNZIONALE

Esempio

HTML:


















Script di startup:

// $('simonboard') indica la tabella// 5 il numero massimo di quadrati da colorare

new Board($('simonboard')).start(5);

Il colore predefinito per il quadrato

Tabella da utilizzare

Lo script

var Tile = Class.create({ initialize: function(color, element) { this.color = color; this.element = element; }, blink: function() { this.element.style.backgroundColor = this.color; new Effect.Opacity(this.element, {duration:2, from:1.0, to:0}); // Scrip.aculo.us }});

var Board = Class.create({ initialize: function(boardElement) { this.tiles = boardElement.select("td").map(function(element){return new Tile(element.id, element);}); },//numero massimo di blocchi da colorare start: function(steps) { var boardSize = this.tiles.length; var tempTiles = this.tiles; //serve per problemi di scope si corregge usando la funzione bind() $R(1, steps).each(function(i){ //funzione di Prototype che riempe un array con un range di valorivar index = Math.ceil(Math.random() * boardSize);var tile = tempTiles[index-1];window.setTimeout(function() { tile.blink(); }, 500 * index);}); }});

Un concetto utile: bind

start: function(steps) { var boardSize = this.tiles.length; $R(1, steps).each(function(i) {var index = Math.ceil(Math.random() * boardSize);var tile = this.tiles[index-1];window.setTimeout(function() { tile.blink(); }, 500 * index);}.bind(this)); }

Il bind serve ad evitare problemi di scope, se lo avessi omesso il this considerato dalla funzione sarebbe stato l'oggeto window.

In Javascript tutte le funzioni sono eseguite in un determinato contesto e questo referenziabile tramite la parola chiave da this

Le funzioni utilizzate come closure sono funzioni globali, quindi hanno il contesto globale

Strumenti utili

Log4J

Debugger

JUnit

JMock e simili

BlackbirdJS

Firebug

JSUnit

JSMock

Siamo abituati ad avere una marea di strumenti a nostra disposione javascript non ci deluder!

Logging: Log4J BlackbirdJS

Debug: Java Debugger Firebug

Unit Test: JUnit JSUnit [1]

Unit Test: JUnit JSUnit [2]

Unit Test: JUnit JSUnit [3]

Unit Test: JUnit JSUnit [4]

MockObject: JMock JSMock [1]

Classe sotto test (CUT)

function Worker() {this.getValue = function() { /* ... */}this.isFinished = function() {/* ... */}}

Fixture

function doWork(worker) {if(worker.isFinished()) {return worker.getValue();} else {return null;}}

Test

function test_doWork() {var mControl = new MockControl();worker = mControl.createMock(Worker);worker.expects().isFinished().andReturn(true);worker.expects().getValue().andReturn('hello');var result = doWork(worker);assertEquals('hello', result);mControl.verify();}

MockObject: JMock JSMock [2]

Classe sotto test (CUT)

function Worker() {this.getValue = function() { /* ... */}this.isFinished = function() {/* ... */}}

Fixture

function doWork(worker) {if(worker.isFinished()) {return worker.getValue();} else {return null;}}

Test

function test_doWork_null() {var mControl = new MockControl();worker = mControl.createMock(Worker);worker.expects().isFinished().andReturn(false);var result = doWork(worker);assertNull(result);mControl.verify();}

Conclusioni

Bibliografia & Links

www.prototypejs.org

http://script.aculo.us

http://www.prototypejs.org/learn/class-inheritance

http://www.gscottolson.com/blackbirdjs/

http://getfirebug.com/js.html

http://www.jsunit.net/

http://jsmock.sourceforge.net/

http://www.infoq.com/articles/javascript-tdd

http://en.wikipedia.org/wiki/Duck_typing

http://www.prototypejs.org/api/function/bind

http://alternateidea.com/blog/articles/2007/7/18/javascript-scope-and-binding

Q&A

JS?
http://jesty.it
[email protected]@pronetics.it

Muokkaa otsikon tekstimuotoa napsauttamalla

Muokkaa jsennyksen tekstimuotoa napsauttamallaToinen jsennystasoKolmas jsennystasoNeljs jsennystasoViides jsennystasoKuudes jsennystasoSeitsems jsennystasoKahdeksas jsennystasoYhdekss jsennystaso