Sei sulla pagina 1di 5

Sviluppo Di Michele Costabile

Parliamo di questo. Anzi, di this


Per chi sviluppa in Java e C questo una variabile familiare con
il nome inglese this. Ecco il suo corretto utilizzo e i suoi potenziali rischi.

T
his, in inglese questo, il no- di memoria situata ad un certo offset Allinterno della console, sulla riga di
me di una variabile ben nota a da un indirizzo base, si usa listruzione comando, creiamo un oggetto, come
chi programma in C e in Java. segue
Si tratta di una certezza rassicurante, mov eax, [esi + 4]
un puntatore allindirizzo dellogget- >var a = {x:3, y:5}
to attivo. Ecco un esempio canonico, supponiamo che il registro esi punti
scritto in Java alla base di un oggetto di classe Point La risposta che otteniamo, undefined,
e che un int sia 4 byte e abbiamo la non un messaggio di errore, ma solo
public class Point { traduzione di come un ipotetico la notificazione del fatto che non c una
public int x = 0; compilatore potrebbe tradurre this.y risposta per unassegnazione, come se
public int y = 0; in codice assembly. avessimo chiamato una funzione che
non torna un valore, lassegnazione.
//constructor In JavaScript, invece... Se scriviamo a e premiamo invio, la
public Point(int x, int y) { console ci mostra il nostro oggetto
this.x = x; In JavaScript possiamo scrivere
this.y = y; codice che ha una forma molto simile >a
} allesempio sopra e possiamo usare la <Object {x: 3, y: 5}
} keyword this, ma se non entriamo con
tutti e due i piedi dentro la sintassi del Naturalmente, x.a ci porta al contenuto
Nel costruttore di questa funzione, linguaggio, rischiamo di farci molto della variabile
this viene impiegato per discriminare male e dover apprendere la verit
fra i parametri x e y e i membri x e y decodificando i messaggi di errore sulla >a.x
delloggetto. Quando scriviamo this.x, console, invece che dal manuale. <3
possiamo sempre pensare, esattamente Cominciamo a demolire la dot notation,
come in C++, che this un puntatore e ovvero la notazione this.x. Proviamo una sintassi leggermente
x un offset allinterno di una struttura. Per farlo, possiamo aprire una pagina diversa, per iniziare a togliere il velo
Questi costrutti sono stati supportati web a un indirizzo qualsiasi e entrare
da sempre dal codice assembly dei nella console JavaScript, con la >a[x]
processori principali. Per esempio combinazione di tasti ctrl-shift-J, o alt- <3
sullarchitettura Intel x86, per caricare in cmd-J sul Mac, che funziona in Chrome
un registro il contenuto di una locazione e Firefox. La sintassi a[x] potrebbe somigliare

142

000_Rub_Sviluppo_302_5p.indd 142 27/04/16 13:06


RUBRICHE > Sviluppo

Abbiamo visto che una funzione pu


avere propriet, come un oggetto.
Proviamo a farci avventurosi.
Ridefiniamo la funzione cos:

>function f() { return this.a }


>f.a = test

Ci aspettiamo che stampi il valore


del campo che abbiamo associato alla
funzione, ma qui restiamo delusi: quello
che otteniamo

<Object {x: 3, y: 5, inoltre: 7}

Quello che accaduto che this.a ha


restituito un riferimento, non al campo
a, che abbiamo appena definito nella
funzione, ma alloggetto a che abbiamo
Un libro su EcmaScript 5, consultabile gratuitamente online, per chi volesse approfondire definito in precedenza nello scope
possibile acquistarlo per effettuare il download in formato elettronico. globale. This, infatti solo un dizionario
di default che viene associato al contesto
di esecuzione del momento. Quale sia
questo dizionario dipende dal ruolo
della funzione.

Nessun errore. Possiamo usare variabili Tre tipi di funzioni


anche per creare propriet, come in
questo esempio Ci sono tre tipi di funzioni: funzioni
pure, costruttori e metodi.
>d = inoltre Le funzioni pure, dette real functions,
>a[d] = 7 sono quelle che non sono definite
>a come propriet di qualche oggetto,
<Object {x: 3, y: 5, inoltre: 7} quindi stanno nello scope globale.
Dove cominciano i guai Sono sostanzialmente variabili, con la
propriet interessante di poter essere
eseguite, e sono definite in uno di questi
modi:

function f(x,y) {return x+y}

oppure cos

Un libro gratuito su EcmaScript 6, dello stesso autore e con la stessa licenza di utilizzo. f = function(x,y) {return x+y}

al riferimento a un elemento di array, >a[c] Queste funzioni, in effetti, le ritroviamo


se non fosse per il fatto che lindice <3 come propriet delloggetto globale,
una stringa. La possibilit di indicare quindi this.f e window.f stampano il testo
una propriet in un oggetto con un in- Confermando, cos, il fatto che la nota- della funzione nel log della console.
dice alfanumerico, ci conduce a vedere zione a oggetti di JavaScript non altro Il codice della funzione pu essere
loggetto per quello che : un dizionario che unabbreviazione per una notazione ottenuto con f.toString().
dati con un po di syntactic sugar per basata su dizionari. Il secondo caso, comprende le funzioni
supportare la dot notation. Qundi, ogni oggetto JavaScript un utilizzate come costruttori di oggetti.
Per ribadire il concetto, proviamo a dizionario, anche le funzioni. Definia- In effetti, queste funzioni non hanno
spingerci pi in l. Creiamo una varia- mone una niente di particolare, se non il fatto di
bile che abbia per valore la stringa x. essere usate con la parola chiave new
>function f() { return 0 } davanti e di sfruttare la semantica
>c = x particolare delluso di this e return che
<x E diamo un valore a una propriet lambiente di esecuzione gli accorda.
delloggetto funzione Per convenzione, gli si impone un nome
Possiamo usare la variabile come indice maiuscolo per identificarle, ma il loro
nelloggetto >f.a = ciao uso non raccomandato.

>
143

000_Rub_Sviluppo_302_5p.indd 143 27/04/16 13:06


RUBRICHE > Sviluppo

come in qualsiasi altro linguaggio. La


seconda, uninvocazione esplicita
attraverso il metodo apply, che ogni
funzione eredita dallantenato originale,
e ha due parametri: un oggetto e un
array contenente i parametri, su cui
torneremo fra poco.
La terza modalit di invocazione,
labbiamo vista, con la parola chiave
new, nella costruzione di oggetti.

A ciascuno il suo this

Ora che abbiamo chiarito la tassonomia


dei diversi tipi di funzione, possiamo
usare questa divisione per individuare
loggetto predefinito, che sar diverso
in tutti e tre i casi.
Per le funzioni pure, loggetto
predefinito lo scope globale, cio
loggetto window, nel browser.
Questo un fatto molto importante da
In questo schema la rappresentazione dei (pochi) registri di un processore Intel 8086, ricordare, perch si possono commettere
unarchitettura che ancora sopravvive come sottoinsieme sulle Cpu correnti a 64 bit. un sacco di errori contando sul contesto,
come, per esempio, in questo caso

>a = 5; o = { a: 3, f: function()
{return a}}
>o.f()

Neanche a dirlo: questo codice stampa


5, non 3.
Proviamo un caso pi convoluto, il
codice seguente:

o = {
a: 3,
f: function() {
g = function() {}
}
};
o.f();

dopo linvocazione di o.f() la funzione


g definita nelloggetto globale, ove
esiste come windowg.
Sar per questo che esiste la possibilit
di forzare un this diverso dalloggetto
La home page di uno dei membri del comitato di standardizzazione di EcmaScript, un sito
globale nellesecuzione di una funzione,
da tenere docchio, sia per le notizie, sia per gli articoli, ricco di indicazioni per lo sviluppo.
usando il metodo apply ereditato, come
in questo esempio

Infine, abbiamo le funzioni identificate modi principali: mettendo una coppia Si pu forzare un oggetto di default
come metodi, che non sono altro che di parentesi dopo il nome, o usandole la specifico, invocando una funzione con
funzioni che sono propriet di oggetti loro propriet predefinita apply. Quindi apply.
diversi dallo scope globale, ossia non queste due righe stampano lo stesso Per esempio,
stanno in window. risultato
o = {a: 2, b:4}
Tre schemi di invocazione >f(3, 2) function f() { return this.a }
>f.apply(null, [3, 2]) f.apply(o, [])
Le funzioni sono variabili come tutte le
altre, ma possono essere eseguite, in due La prima, una chiamata a funzione Questa sintassi pu essere utile negli

144

000_Rub_Sviluppo_302_5p.indd 144 27/04/16 13:06


RUBRICHE > Sviluppo

internals del linguaggio, ma non ci <3 capita di continuo, in ragione della


sembra che faccia intravedere una Non chiami, richiameremo noi natura single-threaded di JavaScript di
prassi raccomandabile. creare funzioni anonime da passare
Possiamo riuscire a scassare anche a altri oggetti, che le richiamano in
Funzioni di costruzione questo codice. Se la funzione incr seguito. Se pensiamo, per esempio, alle
invece di essere invocata direttamente, interfacce di jQuery o di qualsiasi altro
nel caso di costruttori, this punta passata a qualche altra funzione framework, ci sono callback ovunque.
allistanza delloggetto costruito, per che esegue il riferimento a funzione Facciamo un esempio di creazione di
esempio, la funzione ottenuto, lesecuzione ha un contesto una funzione anonima che deve agire
diverso. Facciamo un esempio: sulle variabili di un oggetto:
function Point(x, y) { consideriamo il nel codice che segue:
this.x = x; var obj = {
this.y = y; var contatore = { nome: Qui,
} conteggio: 0, amici: [Quo, Qua],
incr: function() { loop: function() {
restituisce un oggetto con due propriet. this.conteggio++; this.amici.
Questa sintassi ha un pericolo nascosto: return this.conteggio; forEach(function(friend) {
se invece di } console.log(this.nome +
}; knows + friend);
var p = new Point(3, 2) }, this);
Definiamo una funzione che durante }
scriviamo per errore la sua esecuzione ne invoca unaltra, };
ottenuta per riferimento
var p = Point(3,2) Abbiamo creato un oggetto con una
function chiamami(func) { propriet nome, una propriet amici,
otteniamo un disastro: func(); di tipo array e una funzione, loop, che
} esplora questo array con un forEach,
>var p = Point(3,2) al quale passa una funzione callback.
<undefined e proviamo a avviarla Nella callback, facciamo ingenuamente
>window.x riferimento alla propriet amici, e
<3 chiamami(contatore.incr); questo causer un errore in esecuzione,
>window.y perch la propriet nome di this sar
<2 Il metodo incr viene invocato, ma si undefined.
dimenticato di essere un metodo Questo frammento di codice molto
La variabile p non un oggetto, ma ed una semplice funzione, come simile concettualmente a situazioni
undefined, perch Point non restituisce una qualsiasi funzione definita nello che capitano di frequente, nel codice
nessun valore. Quanto a x e y, sono scope globale. Per via di questo reale. Ci sono almeno due sistemi
create nello scope globale. Disastro. declassamento, il suo this, viene messo per eliminare il problema. Il primo
in ombra dal riferimento alloggetto consiste nel copiare this in una variabile
Metodi globale che il default. Questo, forse, da utilizzare nelle callback, di solito
non un esempio cos familiare, ma chiamata that oppure self.
Nel caso di metodi, this si comporta in
modo adeguato alle aspettative, cio
un riferimento alloggetto di cui il
metodo una propriet, come in questo
esempio.
Un test per this IN HTML
<!DOCTYPE html>
var contatore = {
<html lang=en>
conteggio: 0, <head>
incr: function() { <meta charset=UTF-8>
this.conteggio++; <title>Testing this</title>
return this.conteggio; <script type=text/javascript src=loops.js></script>
} </head>
}; <body>
<script>
Ecco un esempio di uso: console.log(this === window in una funzione top
level in un tag script);
>contatore.incr() console.log(this === window); // true
<1 </script>
>contatore.incr() </body>
<2 </html>

>contatore.incr()

145

000_Rub_Sviluppo_302_5p.indd 145 27/04/16 13:06


RUBRICHE > Sviluppo

var obj = { Conclusione luogo, la quantit di codice sul web


nome: Qui, tale da obbligare tutti a una forte
amici: [Quo, Qua], Abbiamo fatto un lungo excursus attenzione per la compatibilit col
loop2: function() { in porzioni abbastanza esoteriche passato, possiamo contare sul fatto che
use strict; del linguaggio. I punti chiave del il futuro somiglier molto al presente,
var that = this; nostro viaggio, sono linizio e la ma con diversi miglioramenti.
this.amici. fine. Allinizio presentiamo il modo Riguardo alla fioritura di linguaggi
forEach(function(friend) { corretto di leggere la dot notation, la alternativi, il team di Angular e quello
console.log(that.nome + base per comprendere la struttura del di Ionic hanno optato per Typescript,
amico di + friend); linguaggio, senza farsi ingannare dalla unaltra creatura di Microsoft e di
}); sintassi. Alla fine, mettiamo in guardia Anders Hejlsberg, che passato
} contro un problema molto frequente, per Delphi a .net. Sicuramente,
} che causa errori, non sempre questo rende Typescript un
facili da riconoscere, nel linguaggio rilevante e
Questa volta, eseguendo obj.loop2() codice articolato e ricco Si preparano destinato a affermarsi
avremo loutput corretto: di callback e proponiamo
delle soluzioni.
cambiamenti sul web, almeno fra
chi sceglie questi
obj.loop2() Fra tutte le soluzioni, Il linguaggio ufficiale framework. TypeScript
Qui amico di Quo la pi radicale sarebbe EcmaScript 5 sta per stato scelto perch
Qui amico di Qua riformare il linguaggio, pasare alla versione 6 molto pi simile
per togliere questi evidenti chiamata ES6 a JavaScript di altre
Una seconda possibilit consiste nel svarioni sintattici. In effetti, possibilit, come Dart e,
bind esplicito di this nella definizione quello che sta accadendo con poich compila in JavaScript
della funzione: come segue: la transizione alla versione 2015 dello semplice, compatibile con tutte le
standard EcmaScript (ES6), da lungo librerie di software che si trovano sul
var obj = { tempo attesa, che porter soluzioni a web. Per levoluzione futura, ES6
nome: Qui, questi problemi e a molti altri. oramai in arrivo, e anche ES7 lo segue a
amici: [Quo, Qua], I segni di insoddisfazione sono ruota. Anche loro saranno compatibili
loop3: function() { ovunque nellindustria: Google ha con il codice esistente, ma i browser
use strict; creato diverso tempo fa un linguaggio arriveranno in ordine sparso con le
this.amici. alternativo chiamato Dart, Microsoft nuove funzioni.
forEach(function(friend) { ha creato Typescript, un linguaggio Questo, per, non ci impedisce di
console.log(this.nome + simile a JavaScript, con variabili usare adesso le evoluzioni future
knows + friend); dotate di tipo e funzioni object del linguaggio, in barba al variegato
}.bind(this)); oriented pi pulite, che compila in supporto che offrono i browser, grazie a
} ES3. Ci sono ancora altre varianti, come un tool, chiamato Babel, che compila le
} CoffeeScript. Insomma, molti hanno versioni future del linguaggio in quella
esplorato alternative. di adesso, e permette di iniziare da
Questa soluzione richiede laggiunta subito a usare le estensioni future, una
di una coda alla callback, ma ha il Nel frattempo il linguaggio ufficiale, possibilit molto interessante per fare
pregio di sostituire del tutto il this EcmaScript 5, sta per passare alla pratica e iniziare a strutturare il codice
della funzione, che quindi non corre versione 6, brevemente chiamata ES6 nel modo migliore. Naturalmente, c
il pericolo di creare variabili globali, e ES7 gi sul radar. anche lopzione zero: non fare niente e
se ci scappa un this al posto di un that. Insomma, ci sono cambiamenti in continuare a usare il linguaggio come
Inoltre, dobbiamo riconoscerlo il gioco arrivo e bisogna orientare le vele per adesso, ma attenzione a imparare a
del this e that fa sentire un po puerili. farsi trovare pronti. Rileviamo alcuni danzare intorno alle trappole, che sono
rileggendo la sorgente. punti fermi a cui appoggiarci per molte di pi di quelle che abbiamo
lorientamento strategico. In primo presentato.

Per saperne di pi
http://bit.ly/es5this. Una discussione molto approfondita delluso di this in tutte le situazioni possibili
http://speakingjs.com. Un libro consultabile gratuitamente sul web, per imparare a usare EcmaScript 5
http://exploringjs.com. Un libro consultabile gratuitamente sul web, dedicato a EcmaScript 6
http://learnangular2.com/es6/ Una analisi comparativa di tutti i rami dellevoluzione di JavaScript, da parte
del team di Angular.

146

000_Rub_Sviluppo_302_5p.indd 146 27/04/16 13:06