Concetti di base di JavaScript

Introduzione
jQuery è scritto in JavaScript, un linguaggio di programmazione molto ricco ed espressivo.

Il capitolo si rivolge a chi non conosce il linguaggio, e copre i concetti di base e problemi comuni che possono sorgere quando si lavora con esso. Inoltre, la sezione può essere utile a chi utilizza altri linguaggi di programmazione per capire le peculiarità di JavaScript.

Se siete interessati a saperne di più sul linguaggio, si può leggere il libro JavaScript: The Good Parts che Douglas Crockford ha scritto.

Sintassi di base
Comprendere dichiarazioni, nomi di variabile, spaziatura, e altre sintassi di base JavaScript
2.1: Dichiarazione semplice di una variabile
[code lang=”javascript”] var foo = ‘ciao mondo’;
[/code]
2.2: Gli spazi non hanno alcun valore al di fuori delle virgolette
[code lang=”javascript”] var foo =     ‘ciao mondo’;
[/code]
2.3: Le parentesi indicano la priorità
[code lang=”javascript”] 2 * 3 + 5; // ritorna 11; il prodotto si esegue prima
2 * (3 + 5); // ritorna 16; per le parentesi, la somma si esegue prima
[/code]
2.4: La tabulazione migliora la lettura del codice, ma non ha un significato speciale
[code lang=”javascript”] var foo = function() {
console.log(‘ciao’);
};
[/code]
Operatori
Operatori di base
Gli operatori di base permettono la manipolazione di valori.
2.5: Concatenazione
[code lang=”javascript”] var foo = ‘ciao’;
var bar = ‘mondo’;

console.log(foo + ‘ ‘ + bar); // ‘ciao mondo’
[/code]

2.6: Moltiplicazione e divisione
[code lang=”javascript”] 2 * 3;
2 / 3;
[/code]
2.7: Incremento e decremento
[code lang=”javascript”] var i = 1;

var j = ++i; // incremento anticipato: j è uguale a 2; i è uguale a 2
var k = i++; // incremento posticipato: k è uguale a 2; i è uguale a 3
[/code]

Lavorare con i numeri e le stringhe
In JavaScript, quando si lavora con i numeri e con le stringhe può causare risultati imprevisti.
2.8: Somma vs. concatenazione
[code lang=”javascript”] var foo = 1;
var bar = ‘2’;

console.log(foo + bar); // errore: la console di debug mostra 12
[/code]

2.9: Forzare una stringa ad agire come un numero
[code lang=”javascript”] var foo = 1;
var bar = ‘2’;

// il costruttore ‘Number’ obbliga alla
// stringa di comportarsi come un numero
console.log(foo + Number(bar)); // la console di debug mostra 3
[/code]

Il costruttore Number, quando viene chiamato come una funzione (come nell’esempio) obbliga al suo argomento a comportarsi come un numero. È inoltre possibile utilizzare l’operatore somma unaria, che ritorna lo stesso risultato:
2.10: Forzare una stringa per agire come un numero (somma unaria)
[code lang=”javascript”] console.log(foo + +bar);
[/code]
Operatori Logici
Gli operatori logici permettono valutare una serie di operandi utilizzando operazioni AND e OR.
2.11: Operatori Logici AND e OR
[code lang=”javascript”] var foo = 1;
var bar = 0;
var baz = 2;

foo || bar; // ritorna 1, il quale è vero (true)
bar || foo; // ritorna 1, il quale è vero (true)

foo && bar; // ritorna 0, il quale è falso (false)
foo && baz; // ritorna 2, il quale è vero (true)
baz && foo; // ritorna 1, il quale è vero (true)
[/code]

L’operatore || (OR logico) restituisce il valore del primo operando, se questo è vero, altrimenti restituisce il valore del secondo operando. Se entrambi gli operandi sono falsi restituisce false (falso). L’operatore && (AND logico) restituisce il valore del primo operando se questo è falso, altrimenti restituisce il valore del secondo operando. Quando entrambi i valori sono veri ritorna vero (true), altrimenti restituisce falso.

È possibile consultare la sezione “Elementi Vero e Falso” per ulteriori dettagli su quali valori vengono valutati come true e quali vengono valutati come false.

Talvolta si può notare che alcuni sviluppatori utilizzino questa logica per il controllo del flusso invece di utilizzare la dichiarazione if. Per Esempio:

[code lang=”javascript”] // fare qualcosa con foo se foo è vero
foo && doSomething(foo);

// stabilire bar uguale a baz se baz è vero;
// caso contrario, stabilire bar uguale al
// valore di createBar()
var bar = baz || createBar();
[/code]

Questo stile dichiarazione è molto elegante e concisa, ma può essere difficile da leggere (specialmente per i principianti). È per questo si esplicita, per riconoscerlo durante la lettura del codice. Tuttavia, il suo uso non è raccomandato a meno che non si ha dimestichezza con il concetto e il comportamento.

Operatori di Confronto
Gli operatori di confronto consentono di verificare se certi valori sono equivalenti o identiche.
2.12: Operatori di confronto
[code lang=”javascript”] var foo = 1;
var bar = 0;
var baz = ‘1’;
var bim = 2;

foo == bar; // ritorna false
foo != bar; // ritorna true
foo == baz; // ritorna true; fare attenzione!

foo === baz; // ritorna false
foo !== baz; // ritorna true
foo === parseInt(baz); // ritorna true

foo > bim; // ritorna false
bim > baz; // ritorna true
foo <= baz; // ritorna true
[/code]

Codice Condizionale
A volte si desidera eseguire un blocco di codice in determinate condizioni. Le strutture di controllo del flusso – attraverso l’uso di istruzioni if ??ed else permettono di farlo.
2.13: Controllo del flusso
[code lang=”javascript”] var foo = true;
var bar = false;

if (bar) {
// questo codice non verrà mai eseguito
console.log(‘ciao!’);
}

if (bar) {
// questo codice non si eseguirà
} else {
if (foo) {
// questo codice si eseguirà
} else {
// si eseguirà se foo e bar sono falsi (false)
}
}
[/code]

In una linea singola, quando si scrive un’istruzione if, le parentesi non sono strettamente necessari, ma è raccomandato in quanto rende il codice molto più leggibile.

È necessario essere consapevoli di non definire funzioni con lo stesso nome più volte all’interno di istruzioni if/else, giacché si potrebbe ottenere risultati inaspettati.

Elementi Veri e Falsi
Per controllare il flusso correttamente, è importante capire quali tipi di valori sono “veri” e che “false”. A volte, alcuni valori possino sembrare una cosa, ma finiscono per essere un’altra.
2.14: Valori che ritornano il vero true
[code lang=”javascript”] ‘0’;
‘qualunque stringa’;
[]; // un array vuoto
{}; // un oggetto vuoto
1; // qualsiasi numero diverso da zero
[/code]
2.15: Valori che ritornano il falso false
[code lang=”javascript”] 0;
”; // una stringa vuota
NaN; // la variabile JavaScript "not-a-number" (non è un numero)
null; // un valore nullo
undefined; // // fare attenzione — (undefined) può essere ridefinito
[/code]
Variabili condizionali utilizzando l'operatore ternario
A volte si desidera impostare il valore di una variabile in funzione a una certa condizione. Per farlo si può utilizzare una dichiarazione if/else, ma in molti casi è più conveniente usare l’operatore ternario. [Definizione:. L’operatore ternario valuta una condizione, se la condizione è vera, restituisce un certo valore, altrimenti restituisce un valore diverso] 2.16: L'operatore ternario
[code lang=”javascript”] [/code]
L’operatore ternario può essere utilizzato senza restituire un valore alla variabile, ma questo uso è generalmente sconsigliato.
Dichiarazione Switch
Invece di usare una serie di istruzioni if/else/else if/else, a volte può essere utile usare l’istruzione switch. [Definizione: un’istruzione Switch valuta il valore di una variabile o espressione ed esegue diferenti blocchi di codice a seconda di quel valore.] 2.17: Una dichiarazione Switch
[code lang=”javascript”] switch (foo) {

case ‘bar’:
alert(‘il valore è bar’);
break;

case ‘baz’:
alert(‘il valore è baz’);
break;

default:
alert(‘impostazione predefinita, questo codice verrà eseguito’);
break;

}
[/code]

Istruzioni switch sono poco utilizzati in JavaScript, perché lo stesso comportamento può essere ottenuto attraverso la creazione di un oggetto, che ha più potenzialità perché si può riutilizzare, usarlo per i test, e così via.
Per Esempio:
[code lang=”javascript”] var stuffToDo = {
‘bar’ : function() {
alert(‘il valore è bar’);
},

‘baz’ : function() {
alert(‘il valore è baz’);
},

‘default’ : function() {
alert(‘impostazione predefinita, questo codice verrà eseguito’);
}
};

if (stuffToDo[foo]) {
stuffToDo[foo]();
} else {
stuffToDo[‘default’]();
}
[/code]

Più avanti si tratterà il concetto di oggetti.
Cicli
I cicli (loops in inglese) permettono eseguire un blocco di codice un certo numero di volte.
2.18: Cicli
[code lang=”javascript”] // mostra nella console ‘tentativo 0’, ‘tentativo 1’, …, ‘tentativo 4’
for (var i=0; i<5; i++) {
console.log(‘tentativo ‘ + i);
}
[/code] Si noti che nell’esempio si utilizza la parola var prima della variabile i, questo significa che detta variabile è all’interno della sua portata, o ambito, (in inglese scope) del ciclo. Più avanti in questo capitolo si esaminerà in modo approfondito il concetto di portata.
Cicli utilizzando FOR
Un ciclo utilizzando for si compone da quattro Stati e ha la seguente struttura:
[code lang=”javascript”] for ([espressioneIniziale]; [condizione]; [incrementoDellaEspressione])
[corpoCiclo] [/code]
Lo stato espressioneIniziale viene eseguito una solavolta, prima che il ciclo cominci. Questo dà la possibilità di preparare o di dichiarare le variabili.

Lo stato condizione viene eseguita prima di ogni iterazione, e restituisce un valore che decide se il ciclo deve continuare oppure no. Se lo stato condizionale valuta un valore come falso il ciclo si interrompe.

Lo stato incrementoDellaEspressione viene eseguito alla fine di ogni ripetizione e offre l’opportunità di modificare lo stato di variabili importanti. Di solito, questo stato comporta l’incremento o il decremento di un contatore.

Il corpoCiclo è il codice da eseguire in ogni iterazione del ciclo. In genere ci sono più istruzioni che devono essere eseguiti e così li avvolgono in un blocco ({…}).

Un tipico ciclo utilizzando for:
2.19: Un tipico ciclo utilizzando for

[code lang=”javascript”] for (var i = 0, limit = 100; i < limit; i++) {
// Questo blocco di codice viene eseguito 100 volte
console.log(‘Attualmente a ‘ + i);
// Nota: L’ultimo record da visualizzare
// nella console sarà "Attualmente a 99"
}
[/code]
Cicli utilizzando WHILE
Un ciclo utilizzando while è simile ad un’istruzione condizionale if, tranne che il corpo continuerà a funzionare fino a quando la condizione da valutare sia falsa.
[code lang=”javascript”] for ([espressioneIniziale]; [condizione]; [incrementoDellaEspressione])
[corpoCiclo] [/code]
Un típico bucle utilizzando while:
2.20: Un típico bucle utilizzando while
[code lang=”javascript”] var i = 0;
while (i < 100) {

// Questo blocco di codice verrà eseguito 100 volte
console.log(‘Attualmente a ‘ + i);

i++; // incrementa la variabile i

}
[/code]

Si può notare che nell’esempio viene incrementato il contatore all’interno del corpo del ciclo, ma è anche possibile combinare la condizione e l’incremento, come illustrato di seguito:
2.21: Ciclo utilizzando while con la combinazione della condizione e l'incremento
[code lang=”javascript”] var i = -1;
while (++i < 100) {
// Questo blocco di codice verrà eseguito 100 volte
console.log(‘Attualmente a ‘ + i);
}
[/code]
la variabile i inizia a -1 e poi utilizza l’incremento anticipato (++i).
Cicli utilizzando do-while
Questo ciclo è come usare while, tranne che il corpo viene eseguito almeno una volta prima che la condizione venga valutata.
[code lang=”javascript”] do [corpoCiclo] while ([condizione])
[/code]
2.22: Un ciclo do-while
[code lang=”javascript”] do {

// Anche quando la condizione è falsa
// il corpo del ciclo viene eseguito almeno una volta.

alert(‘Ciao!’);

} while (false);
[/code]

Tali cicli sono abbastanza insoliti, perché raramente si ha bisogno di un ciclo che esegua un giro almeno una volta. In entrambi i casi si dovrebbe essere a conoscenza.
Break e Continue
Di solito, la fine dell’esecuzione di un ciclo coinciderà quando la condizione non continui a valutare un valore vero, tuttavia è anche possibile fermare un ciclo utilizzando l’istruzione break all’interno del corpo.
2.23: Fermare un ciclo con break
[code lang=”javascript”] for (var i = 0; i < 10; i++) {
if (qualcosa) {
break;
}
}
[/code]
Può anche accadere che si desidera continuare il ciclo senza dover eseguire più dichiarazioni del corpo del ciclo. Questo può essere fatto utilizzando l’istruzione continue.
2.24: Saltare alla seguente iterazione di un ciclo
[code lang=”javascript”] for (var i = 0; i < 10; i++) {

if (qualcosa) {
continue;
}

// La seguente dichiarazione sarà eseguita
// se la condizione ‘something’ non si compie
console.log(‘I have been reached’);

}
[/code]

Parole Riservate
JavaScript ha un numero di “parole riservate”, o parole che sono speciali all’interno dello stesso linguaggio. Si dovrebbe utilizzare queste parole quando si ha bisogno per il suo uso specifico.

  • abstract
  • boolean
  • break
  • byte
  • case
  • catch
  • char
  • class
  • const
  • continue
  • debugger
  • default
  • delete
  • do
  • double
  • else
  • enum
  • export
  • extends
  • final
  • finally
  • float
  • for
  • function
  • goto
  • if
  • implements
  • import
  • in
  • instanceof
  • int
  • interface
  • long
  • native
  • new
  • package
  • private
  • protected
  • public
  • return
  • short
  • static
  • super
  • switch
  • synchronized
  • this
  • throw
  • throws
  • transient
  • try
  • typeof
  • var
  • void
  • volatile
  • while
  • with
Vettori o Matrici
I vettori (in inglese arrays) sono liste di valori a indice zero (in inglese zero-index), cioè il primo elemento della matrice è l’indice 0. sono un modo conveniente per memorizzare un insieme di dati correlati (come stringhe), ma in realtà, un array può includere più tipi di dati, compresi altri array.
2.25: Un vettore semplice
[code lang=”javascript”] var myArray = [ ‘ciao’, ‘mondo’ ];
[/code]
2.26: Accedere agli elementi dell'array attraverso il suo indice
[code lang=”javascript”] var myArray = [ ‘ciao’, ‘mondo’ ];
[/code]
2.27: Ottenere il numero di elementi dell'array
[code lang=”javascript”] var myArray = [ ‘ciao’, ‘mondo’ ];
console.log(myArray.length); // mostra ‘2’ nella console
[/code]
2.28: Modificare il valore di un elemento di un array
[code lang=”javascript”] var myArray = [ ‘ciao’, ‘mondo’ ];
myArray[1] = ‘modificato’;
[/code] Come mostrato nell’esempio “Modificare il valore di un elemento di un array” è possibile modificare il valore di un elemento di un array, in genere non è consigliabile.
2.29: Aggiungere elementi ad un array
[code lang=”javascript”] var myArray = [ ‘ciao’, ‘mondo’ ];
myArray.push(‘nuovo’);
[/code]
2.30: Lavorando con gli array
[code lang=”javascript”] var myArray = [ ‘c’, ‘i’, ‘a’, ‘o’ ];
var myString = myArray.join(”); // ‘ciao’
var mySplit = myString.split(”); // [ ‘c’, ‘i’, ‘a’, ‘o’ ] [/code]
Oggetti
Gli oggetti sono elementi che possono contenere zero o più insiemi di coppie di nomi chiave e valori associati a tale oggetto. I nomi possono essere qualsiasi parola o numero valido. Il valore può essere qualsiasi tipo di valore: un numero, una stringa, un array, una funzione, anche un altro oggetto.

[Definizione: Quando uno dei valori di un oggetto è una funzione, è chiamato come metodo dell’oggetto.] In caso contrario, essi sono chiamati proprietà..

È interessante notare che in JavaScript, quasi tutto è un oggetto – array, funzioni, numeri, anche le stringhe – e tutti possiedono proprietà e metodi.

[code lang=”javascript”] var myObject = {
sayHello : function() {
console.log(‘ciao’);
},

myName : ‘Rebecca’
};

myObject.sayHello(); // si chiama il metodo sayHello, che
// visualizza sulla console ‘Ciao’
console.log(myObject.myName); // si chiama la proprietà myName, che
// mostra ‘Rebecca’ nella console
[/code]

Si noti che quando si creano oggetti letterali, il nome della proprietà può essere qualsiasi identificatore JavaScript, una stringa (racchiusa tra virgolette) o un numero:
[code lang=”javascript”] var myObject = {
validIdentifier: 123,
‘qualche stringa’: 456,
99999: 789
};

[/code]

Gli oggetti letterali possono essere molto utile per l’organizzazione del codice, per maggiori informazioni potete leggere l’articolo (in inglese) Using Objects to Organize Your Code di Rebecca Murphey.

Funzioni
Le funzioni contengono blocchi di codice che viene eseguito ripetutamente. Alle stesse possono essere passati argomenti, e facoltativamente la funzione può restituire un valore.

Le funzioni possono essere creati in diversi modi:
2.32: Dichiarazione di una funzione

[code lang=”javascript”] function foo() { /* fa qualcosa */ }
[/code]
2.33: Dichiarare una funzione denominata
[code lang=”javascript”] var foo = function() { /* fa qualcosa */ }
[/code]
È preferibile il metodo della funzione denominata a causa di alcuni motivi tecnici profondo. Probabilmente troverete i due metodi quando si revisiona il codice JavaScript.
Utilizzo delle Funzioni
2.34: Una semplice funzione
[code lang=”javascript”] var greet = function(person, greeting) {
var text = greeting + ‘, ‘ + person;
console.log(text);
};

greet(‘Rebecca’, ‘Ciao’);
[/code]

2.35: Una funzione che restituisce un valore
[code lang=”javascript”] var greet = function(person, greeting) {
var text = greeting + ‘, ‘ + person;
return text;
};

console.log(greet(‘Rebecca’,’ciao’));
[/code]

2.36: Una funzione che restituisce un'altra funzione
[code lang=”javascript”] var greet = function(person, greeting) {
var text = greeting + ‘, ‘ + person;
return function() { console.log(text); };
};

var greeting = greet(‘Rebecca’, ‘Ciao’);
greeting();
[/code]

Funzioni Anonime Autoeseguilili
Un modello comune in JavaScript sono le funzioni anonime autoeseguibili. Questo modello consiste in creare un’espressione di funzione ed immediatamente eseguirla. Lo stesso è utile nei casi in cui non si vuole intervenire nei namespace globale, perché nessuna variabile dichiarata all’interno della funzione è visibile dall’esterno.
2.37: Una funzione anonima autoeseguibile
[code lang=”javascript”] (function(){
var foo = ‘Ciao mondo’;
})();

console.log(foo); // indefinito (undefined)
[/code]

Funzioni come Argomenti
In JavaScript, le funzioni sono “cittadini di prima classe” — possono essere assegnati alle variabili o passate ad altre funzioni come argomenti. In jQuery, passare funzioni come argomenti è una pratica molto comune.
2.38: Passare una funzione anonima come argomento
[code lang=”javascript”] var myFn = function(fn) {
var result = fn();
console.log(result);
};

// mostra nella console ‘Ciao mondo’
myFn(function() { return ‘Ciao mondo’; });
[/code]

2.39: Passare una chiamata di funzione come argomento
[code lang=”javascript”] var myFn = function(fn) {
var result = fn();
console.log(result);
};

var myOtherFn = function() {
return ‘Ciao mondo’;
};

// mostra nella console ‘Ciao mondo’
myFn(myOtherFn);
[/code]

Determinazione del tipo di variabile
JavaScript offre un modo per verificare il “tipo” (in inglese type) di una variabile. Tuttavia, il risultato può essere fonte di confusione – per Esempio, il tipo di array è un “object”.

Per ciò, è pratica comune usare l’operatore typeof quando si tratta di determinare il tipo di un valore specifico.
2.40: Determinare il tipo tra differenti variabili

[code lang=”javascript”] var myFunction = function() {
console.log(‘ciao’);
};

var myObject = {
foo : ‘bar’
};

var myArray = [ ‘a’, ‘b’, ‘c’ ];

var myString = ‘ciao;

var myNumber = 3;

typeof myFunction; // ritorna ‘function’
typeof myObject; // ritorna ‘object’
typeof myArray; // ritorna ‘object’ — fare attenzione
typeof myString; // ritorna ‘string’;
typeof myNumber; // ritorna ‘number’

typeof null; // ritorna ‘object’ — fare attenzione

if (myArray.push && myArray.slice && myArray.join) {
// probabilmente è un array
// (questo stile è chiamato, in inglese, "duck typing")
}

if (Object.prototype.toString.call(myArray) === ‘[object Array]’) {
// definitivamente è un array;
// questa è considerata la forma più robusta
// per determinare se un valore è un array.
}
[/code]

jQuery fornisce metodi per determinare il tipo di un certo valore. Questi metodi si vedranno più avanti.
La parola chiave this
In JavaScript, come in molti linguaggi di programmazione object-oriented, this è una parola chiave speciale che fa riferimento all’oggetto in cui il metodo viene invocato. Il valore di this viene determinato utilizzando una serie di semplici passi:

  • Se la funzione viene invocata utilizzando Function.call o Function.apply, this avrà il valore del primo argomento passato al metodo. Se l’argomento è nullo (null) o indefinito (undefined), this farà riferimento all’oggetto globale (l’oggetto window);
  • Se la funzione a invocare viene creata utilizzando Function.bind, this sarà il primo argomento che viene passato alla funzione, al momento della sua creazione;
  • Se la funzione è invocata come metodo di un oggetto, this farà riferimento a detto oggetto;
  • Altrimenti, se la funzione viene invocata come una funzione indipendente, non legata ad alcun oggetto, this farà riferimento all’oggetto globale.
2.41: Una funzione invocata utilizzando Function.call
[code lang=”javascript”] var myObject = {
sayHello : function() {
console.log(‘Ciao! il mio nome è ‘ + this.myName);
},

myName : ‘Rebecca’
};

var secondObject = {
myName : ‘Colin’
};

myObject.sayHello();
// registra ‘Ciao, il mio nome è Rebecca’
myObject.sayHello.call(secondObject);
// registra ‘Ciao, il mio nome è Colin’
[/code]

2.42: Una función creada utilizando Function.bind
[code lang=”javascript”] var myName = ‘the global object’,

sayHello = function () {
console.log(‘Ciao, il mio nome è ‘ + this.myName);
},

myObject = {
myName : ‘Rebecca’
};

var myObjectHello = sayHello.bind(myObject);

sayHello(); // registra ‘Ciao, il mio nome è oggetto globale’
myObjectHello(); // registra ‘Ciao, il mio nome è Rebecca’
[/code]

2.43: Una funzione vincolata ad un oggetto
[code lang=”javascript”] var myName = ‘oggetto globale’,

sayHello = function() {
console.log(‘Ciao, il mio nome è ‘ + this.myName);
},

myObject = {
myName : ‘Rebecca’
},

secondObject = {
myName : ‘Colin’
};

myObject.sayHello = sayHello;
secondObject.sayHello = sayHello;

sayHello(); // registra ‘Ciao, il mio nome è oggetto globale’
myObject.sayHello(); // registra ‘Ciao, il mio nome è Rebecca’
secondObject.sayHello(); // registra ‘Ciao, il mio nome è Colin’
[/code]

A volte, quando si invoca una funzione che si trova all’interno di uno spazio dei nomi (namespace in inglese) ampio, si può essere tentati di salvare il riferimento alla funzione corrente in una variabile più breve ed accessibile. Tuttavia, è importante non farlo nelle istanze dei metodi, giacché possono portare all’esecuzione del codice errato. Per Esempio:
[code lang=”javascript”] var myNamespace = {
myObject : {
sayHello : function() {
console.log(‘Ciao, il mio nome è ‘ + this.myName);
},

myName : ‘Rebecca’
}
};

var hello = myNamespace.myObject.sayHello;

hello(); // registra ‘Ciao, il mio nome è undefined’
[/code]

Per evitare che questi errori si verifichino, è necessario fare riferimento all’oggetto dove il metodo e invocato:
[code lang=”javascript”] var myNamespace = {
myObject : {
sayHello : function() {
console.log(‘Ciao!, il mio nome è ‘ + this.myName);
},

myName : ‘Rebecca’
}
};

var obj = myNamespace.myObject;

obj.sayHello(); // registra ‘Ciao!, il mio nome è Rebecca’
[/code]

Ambito
“L’ambito” (scope in inglese) si riferisce a variabili che sono disponibili in un blocco di codice in un dato tempo. La mancanza di comprensione di questo concetto può essere un’esperienza frustrante durante la depurazione.

Quando una variabile viene dichiarata all’interno di una funzione utilizzando la parola chiave var, è disponibile solo per il codice all’interno della funzione – tutto il codice al di fuori della funzione non può accedere alla variabile. D’altra parte, le funzioni definite all’interno della funzione potranno accedere alla variabile dichiarata.

Le variabili dichiarate all’interno della funzione senza la parola chiave var non rimangono nell’ambito di applicazione della stessa funzione – JavaScript cercherà il luogo dove la variabile è stata precedentemente dichiarata, e nel caso che non sia stata dichiarata, sarà definita nell’ambito globale, il quale può portare a risultati inattesi;
2.44: Le funzioni hanno accesso alle variabili definite all'interno dello stesso ambito

[code lang=”javascript”] var foo = ‘Ciao’;

var sayHello = function() {
console.log(foo);
};

sayHello(); // mostra nella console ‘Ciao’
console.log(foo); // mostra anche nella console ‘Ciao’
[/code]

2.45: Il codice esterno non può accedere alla variabile definita all'interno della funzione
[code lang=”javascript”] var sayHello = function() {
var foo = ‘Ciao’;
console.log(foo);
};

sayHello(); // mostra nella console ‘Ciao’
console.log(foo); // non mostra niente nella console
[/code]

2.46: Variabili con nomi identici ma diversi valori possono esistere in diversi ambiti
[code lang=”javascript”] var foo = ‘mondo’;

var sayHello = function() {
var foo = ‘ciao’;
console.log(foo);
};

sayHello(); // mostra nella console ‘ciao’
console.log(foo); // mostra nella console ‘mondo’
[/code]

[code lang=”javascript”] var myFunction = function() {
var foo = ‘Ciao’;

var myFn = function() {
console.log(foo);
};

foo = ‘mondo’;

return myFn;
};

var f = myFunction();
f(); // registra ‘mondo’ — errore
[/code]

2.48: Ambito folle
[code lang=”javascript”] // a self-executing anonymous function
(function() {
var baz = 1;
var bim = function() { alert(baz); };
bar = function() { alert(baz); };
})();

console.log(baz); // La console non mostra nulla,
// visto che baz è definita nell’ambito
// della funzione anonima

bar(); // bar è definita al di fuori della funzione
// anonima dopo essere stata dichiarata senza la
// parola chiave var; inoltre, come è stata
// definita all’interno della stessa portata di
// baz, è possibile interrogare il valore del baz,
// anche se questa sia definita all’interno
// della portata della funzione anonima

bim(); // bim non è definito per essere accessibile
// al di fuori della funzione anonima,
// quindi viene visualizzato un errore
[/code]

Chiusure
Le chiusure (closures in inglese) sono un’estensione del concetto di ambito (scope) – funzioni che hanno accesso alle variabili che sono disponibili all’interno dell’ambito in cui è stata creata la funzione. Se questo concetto è confuso, non preoccuparsi: si capisce meglio attraverso degli esempi.

Nell’sempio 2.47 il modo in cui le funzioni hanno accesso per cambiare il valore delle variabili. Lo stesso comportamento si verifica nelle funzioni create all’interno dei cicli – la funzione “osserva” il cambiamento nella variabile, anche dopo che la funzione sia stata definita, risultando che ad ogni click appaia una finestra di avviso mostrando il valore 5.
2.49: Come impostare il valore di i?

[code lang=”javascript”] /* questo non si comporta come desiderato */
/* ogni click visualizzerà una finestra di avviso con il valore 5 */
for (var i=0; i<5; i++) {
$(‘<p>click me</p>’).appendTo(‘body’).click(function() {
alert(i);
});
}
[/code]
2.50: Impostare il valore di i utilizzando una chiusura
[code lang=”javascript”] /* soluzione: "clausurare" il valor di i all’interno di createFunction */
var createFunction = function(i) {
return function() { alert(i); };
};

for (var i=0; i<5; i++) {
$(‘<p>click me</p>’).appendTo(‘body’).click(createFunction(i));
}
[/code]

Le chiusure possono anche essere utilizzate per risolvere i problemi con la parola chiave this, la quale è unica per ogni ambito.
2.51: Utilizzando una chiusura per accedere simultaneamente ad istanze di oggetti interni ed esterni
[code lang=”javascript”] var outerObj = {
myName : ‘esterno’,
outerFunction : function () {

// fornisce un riferimento allo stesso oggetto outerObj
// da utilizzare all’interno di innerFunction
var self = this;

var innerObj = {
myName : ‘interno’,
innerFunction : function () {
console.log(self.myName, this.myName);
// registra ‘esterno interno’
}
};

innerObj.innerFunction();

console.log(this.myName);
// registra ‘esterno’
}
};

outerObj.outerFunction();
[/code]

Questo meccanismo può essere utile quando si lavora con funzioni di richiamo o retro-chiamate (callbacks in inglese). Tuttavia, in questi casi è preferibile usare Function.bind per evitare qualunque sovraccarico associatoall’ambito (scope).