8. … ma per oggetto
si intende forse
istanza di una
classe?
9. Classi!? In JavaScript non esistono
Il costruttore è una funzione
function Comodino(colore, cassetti) {
this.colore = colore;
this.cassetti = cassetti;
return this; // facoltativo
};
var comodino = new Comodino(‘Bianco’, 3);
12. un contesto di
esecuzione : this
un insieme di valori
passati come
parametri : arguments
un campo contenente
tutto il codice
13. variadic function
function sum( ) {
var total = 0;
var count = arguments.length;
for(var i = 0; i < count; i++) {
total += arguments[i];
}
return total;
}
18. Lo scope di una variabile è
limitato alla funzione nella
quale la variabile è stata dichiarata
19. Accessibile da tutta
variabile globale l’applicazione
var zoccolo = ’80 millimetri’;
var altezza = function(comodino) {
var altezza_zoccolo = parseInt(zoccolo);
return comodino.altezza
+ altezza_zoccolo;
};
20. Accessibile solo
all’interno della funzione
var zoccolo = ’80 millimetri’;
var altezza = function(comodino) {
var altezza_zoccolo = parseInt(zoccolo);
return comodino.altezza
+ altezza_zoccolo;
};
variabile locale
21. Accessibile solo
all’interno della funzione
function foo( ) {
if ( true) {
var zoccolo = ‘80 millimetri’;
}
alert(zoccolo);
};
foo( );
23. Se la funzione è chiamata
come metodo, il contesto è
l’oggetto al quale appartiene
var comodino = {
…
dimensioni : function( ){
return this.larghezza + ‘x’ + this.altezza
+ ‘x’ + this[‘profondità’] + ‘ mm’;
}
}
24. Se la funzione viene definita
globalmente a livello di
applicazione, il contesto è
l’oggetto globale (window)
var a = 1;
var b = 2;
var c = sum(this.a, this.b);
25. Per una funzione interna il
contesto è quello della
funzione esterna a = 10
var a = 5; var a = 5;
var foo = function( ) { var foo = function( ) {
var a = 0; var a = 0;
var f = function(b){ var f = function(b){
a += b; this.a += b;
}; };
f(5); f(5);
return a; return a;
}; };
foo(); // risultato: 5 foo(); // risultato: 0
26. Cosa succede se chiamiamo una funzione
globale all’interno di una funzione interna?
var value = 0;
var obj = { value : 5 }; Qual è il risultato
di obj.add(3)?
obj.add = function (a) {
var inner = function (){
this.value = sum(this.value, a);
};
inner();
return this.value;
};
obj.add(3);
27. Cosa succede se chiamiamo una funzione
globale all’interno di una funzione interna?
var value = 0;
var obj = { value : 5 };
obj.add = function (a) {
var inner = function (){
this.value = sum(this.value, a);
};
inner();
return this.value;
};
Si riferisce all’oggetto
obj.add(3); globale
28. Cosa succede se chiamiamo una funzione
globale all’interno di una funzione interna?
var value = 0;
var obj = { value : 5 };
obj.add = function (a) {
var inner = function (){
this.value = sum(this.value, a);
};
inner();
return this.value;
};
obj.add(3); Si riferisce all’oggetto
globale
29. Creo una variabile that nel metodo esterno per
passare alla funzione globale il contesto locale
var value = 0;
var obj = { value : 5 };
obj.add = function (a) {
var that = this;
var inner = function (){
that.value = sum(that.value, a);
};
inner();
return this.value;
};
obj.add(3);
30. E se volessimo cambiare il
contesto di esecuzione? Con
il metodo apply si può!
var obj = { value : 5 };
obj.multiply = function(a){
return this.value * a;
}; parametri:
- nuovo contesto
obj.multiply(3); - array di argomenti
var value = 2;
obj.multiply.apply(this, [3]);
31. Cosa succede se nel creare un oggetto mi
dimentico della parola chiave new?
var value = 0;
function Obj(value){
this.value = value;
};
var obj = Obj(5);
obj.value = 10;
Quale valore ho
modificato?
32. Cosa succede se nel creare un oggetto mi
dimentico della parola chiave new?
var value = 0;
function Obj(value){
this.value = value;
};
var obj = Obj(5);
obj.value = 10;
Quale valore ho
modificato?
33. Lo scope delle variabili di una
funzione viene determinato al
momento della sua definizione e
non quando questa viene eseguita
34. function foo( ) {
var a = 123;
bar( );
}; In esecuzione il ritorno
di “a” da parte di bar()
avviene dopo la
function bar( ) { dichiarazione di “a”
return a; ma il risultato è …
};
foo(); // risultato: undefined
Lo scope di bar() al
momento della sua
definizione è globale
35. function foo( ) { function foo( ) {
var a = 123; var a = 123;
bar( ); var bar = function( ) {
}; return a;
};
function bar( ) { return bar();
return a; };
}; foo(); // risultato: 123
foo(); // risultato: undefined Lo scope di bar() al momento
della sua definizione è lo
stesso di foo()
36. Le funzioni interne possono
accedere alle variabili e ai
parametri delle funzioni nelle
quali sono definite
37. global scope
var a = 14; foo scope a
function foo( ) {
var b = 10; bar scope b
function bar( ) {
var c = 3;
c
alert(a+b+c);
};
bar( );
};
foo(); // mostra 27
38.
39. “A closure is formed when one of
those inner functions is made
accessible outside of the function in
which it was contained, so that it
may be executed after the outer
function has returned.”
http://jibbering.com/faq/notes/closures/
40. var obj = function ( ) {
var value = 1;
return {
add : function (a) { value += a; },
getValue : function ( ) { return value; }
}
}( );
obj.add(5);
obj.getValue(); // risultato: 6
41. function foo(arg) {
var bar = function(){
return arg;
};
arg++;
return bar;
};
var bar = foo(5);
bar(); // risultato: 6
42. function foo( ) {
var i, array = [ ];
for(i = 0; i < 3; i++) {
array[ i ] = function( ) {
return i;
}; La funzione anonima
} mantiene un riferimento allo
return array; scope del parent
};
var a = foo( );
Le tre funzioni puntano
a[0]( ); // risultato: 3 entrambe al valore di “i”
a[1]( ); // risultato: 3 terminata l’esecuzione di
a[2]( ); // risultato: 3 foo e quindi del loop
43. function foo( ) {
var i, array = [ ];
for(i = 0; i < 3; i++) {
array[ i ] = ( function( j ) {
return function( ) { return j; }
})( i );
}
La funzione anonima
return array; accetta “i“ come parametro
};
var a = foo( );
a[0]( ); // risultato: 0 Adesso ogni funzione ha
a[1]( ); // risultato: 1 “i” nel suo scope con il
a[2]( ); // risultato: 2 valore i-esimo del loop
44. // funzione con una callback come parametro
function foo(a, b, callback) {
var n = (a * b) + b;
callback(n);
} anonymous function
foo (5, 2, function(n) {
alert("callback result: " + n);
});
46. In JavaScript non esistono classi …
Il costruttore è una funzione
function Comodino(colore, cassetti) {
this.colore = colore;
this.cassetti = cassetti;
return this; // facoltativo
};
var comodino = new Comodino(‘Bianco’, 3);
47. Ogni funzione ha una proprietà
prototype che è il prototipo degli
oggetti creati con quella funzione
typeof Comodino.prototype // risultato: object
48. Il prototipo mantiene in una proprietà
constructor il riferimento alla funzione
che lo ha generato
typeof Comodino.prototype.constructor
// risultato: Function
Comodino.prototype.constructor
// risultato: Comodino( )
49. Invece che inizializzare gli oggetti nel
costruttore lo posso fare con il prototype
function Comodino( ) { };
Comodino.prototype.cassetti = 3;
Comodino.prototype.colore = ‘Bianco’;
…
var comodino = new Comodino( );
comodino.cassetti // risultato: 3
Comodino.prototype.isProtoypeOf(comodino); // true
50. L’aggiunta di una proprietà nel prototipo
si riflette su tutti gli oggetti creati con
quel prototipo
function Comodino( ) { };
Comodino.prototype.cassetti = 3;
Comodino.prototype.colore = ‘Bianco’;
var comodino1 = new Comodino( );
var comodino2 = new Comodino( ); augmentation
Comodino.prototype.altezza = 400;
comodino1.altezza; // risultato: 400
comodino2.altezza; // risultato: 400
57. function Mobile( ) {
this.materiali = [ ‘Legno’ ];
}
function Comodino( ) {
this.colore = ‘Bianco’; prototype chaining
}
// Comodino eredita da Mobile
Comodino.prototype = new Mobile();
var comodino = new Comodino( );
comodino.materiali[0]; // risultato: “Legno”
58. Le proprietà impostate nel costruttore
diventano proprietà di prototipo e
quindi condivise
...
// Comodino eredita da Mobile
Comodino.prototype = new Mobile();
var comodino1 = new Comodino( );
var comodino2 = new Comodino( );
comodino1.materiali.push(‘Vetro’);
comodino1.materiali; // ”Legno, Vetro”
comodino2.materiali; // ”Legno, Vetro”
60. function Mobile( ) {
I metodi devono essere
this.materiali = [ ‘Legno’ ]; aggiunti sul costruttore
} base perché il prototipo
non è visibile dai sottotipi
function Comodino( ) {
this.colore = ‘Bianco’;
Mobile.call(this);
} constructor stealing
var comodino1 = new Comodino( );
var comodino2 = new Comodino( );
comodino1.materiali.push(‘Vetro’);
comodino1.materiali; // ”Legno, Vetro”
comodino2.materiali; // ”Legno”
62. La tecnica Pseudoclassical
Inheritance prende il meglio
dai due pattern precedenti,
utilizzando:
• prototype chaining per i
metodi
• constructor stealing per le
proprietà
63. function Mobile( prezzo ) {
this.materiali = [ ‘Legno’ ];
this.prezzo = prezzo;
}
Mobile.prototype.sconto = function( percentuale ) {
return this.prezzo * percentuale / 100;
};
function Comodino( prezzo, colore ) {
// eredita le proprietà
Mobile.call(this, prezzo);
this.colore = colore;
}
// eredita i metodi
Comodino.prototype = new Mobile ();