What is ‘this’ ?

Introduzione

La comprensione della variabile this è uno dei primi scogli che un programmatore JavaScript deve affrontare.

L’origine delle incomprensioni è principalmente dovuta alla facilità con cui si tende ad estendere a JavaScript concetti che solitamente sono propri della programmazione a oggetti. In questi ambiti il this viene visto come l’oggetto corrente inteso come istanza di una classe.

In JavaScript il concetto di classe è assolutamente assente,  l’oggetto corrente viene determinato in base al cosiddetto invocation pattern.

In JavaScript esistono quattro modi per invocare una funzione:

  • Method Invocation
  • Function Invocation
  • Constructor Invocation
  • Apply Invocation

Method Invocation

Quando una funzione è dichiarata come proprietà di un oggetto, viene chiamata metodo. Quando questo metodo viene invocato, il this è riferito a questo oggetto.

Il seguente codice chiarisce meglio questo concetto

var obj = {
    lunghezza : 12,
    getLunghezza : function(){
        console.log(this);
        return this.lunghezza;
    }
};

var lun = obj.getLunghezza(); // ora lun vale 12 e in console viene loggato l'oggetto "obj"

Method Invocation

Quando una funzione non è una proprietà di un oggetto allora viene invocata come funzione, in questi casi this rappresenta l’oggetto globale (windows nel caso del browser). Un tipico caso di errore è il seguente blocco di codice:

var Test = {    
    lunghezza: 12,    
    getLunghezza : function() {        
        //this == Test        
        var output = function(unita) {            
            //this == window            
            return this.lunghezza + ' ' + unita;       
        };        
        return output('cm');    
    }
};

Test.getLunghezza(); // il valore restituito è "undefined cm"

L’errore è generato per il fatto che all’interno della funzione “output” il this è associato all’oggetto globale (come già detto, window nella maggior parte dei casi) e ovviamente questo oggetto non ha una proprietà lunghezza.

Uno dei classici workaround è quello di salvare un riferimento interno al this associandolo ad un’altra variabile che viene inclusa nella closure associata alla funzione output

var Test = {    
    lunghezza: 12,    
    getLunghezza : function() {        
        //this == Test
        var that = this;
        var output = function(unita) {            
            //this == window
            //MA that == Test
            return that.lunghezza + ' ' + unita;       
        };        
        return output('cm');    
    }
};

Test.getLunghezza(); // il valore restituito ora è "12 cm"

Constructor Invocation

Questo pattern sfrutta la parola riservata new per dare una sintassi confortevole ai programmatori abituati a linguaggi che supportano il concetto di classi per aggirare la scarsa comprensione dell’ereditarietà per prototipi tipica di Javascript.

Questo viene realizzato richiamando una funzione facendola precedere dalla keyword new. In questi casi JavaScript crea un nuovo oggetto linkato al prototype associato alla funzione chiamata e associando il this a questo nuovo oggetto. Sintatticamente viene mimata la creazione tramite costruttore dei tipici linguaggi di programmazione

Riportando l’esempio precedente abbiamo il seguente codice

var Test = function(){    
    this.lunghezza = 12;    
    this.getLunghezza = function(unita) {        
        return this.lunghezza + ' ' + unita;       
    };        
};

var t = new Test();
t.getLunghezza('cm'); // il valore restituito è "12 cm"

È buona pratica usare la lettera maiuscole per il nome di funzione, per indicare il fatto che la funzione deve essere chiamata con la keyword new. Altra buona pratica è effettuare un test sul this per verificare che sia instanceof Test, sollevando una eccezione in caso contrario.

Apply Invocation

Dal momento che in JavaScript ogni funzione è un oggetto, anche la nostra funzione Test può avere dei metodi. Uno dei metodi che sono associati alle istanze di tipo function è apply().

La funzione apply permette di chiamare una funzione impostando dall’esterno il this.

var add = function(){
    return this.uno + this.due;
};
var a = { uno : 3, due :4};
var sum = add.apply(a, null);

In questo caso imponiamo dall’esterno il this che ci ritroveremo all’interno della funzione add.

Riepilogando, una delle cose disturbanti in JavaScript è che il this non è sempre l’oggetto che ci si aspetta. Occorre molta cautela e documentazione sull’uso delle proprie librerie.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.