Categorie
Javascript Programmazione

{JS} this

Contesto di esecuzione

L’interpretazione del codice JavaScript da parte di un engine avviene in uno determinato contesto di esecuzione.
Un contesto di esecuzione è un ambiente circoscritto composto dall’insieme delle variabili accessibili al momento dell’esecuzione dell’istruzione.
Nel contesto di esecuzione sono compresi gli eventuali argomenti di un funzione e l’oggetto this.

L’oggetto this

Una parola molto importante nella programmazione Javascript è this.
Grazie a questo particolare identificatore, infatti, è possibile far riferimento “a se stesso”.
L’utilizzo di this in Javascript differisce rispetto ad altri linguaggi di programmazione OOP, infatti, Javascript non conosce il concetto di classe e pertanto non è sempre facile identificare l’oggetto al quale this si riferisce. Il problema principale, quindi, è identificare il contesto al quale this fa riferimento.

In JavaScript, puoi utilizzare la  parola chiave this nei contesti global e function. Inoltre, il comportamento di  this cambia tra modalità rigorosa (Strict mode) e non rigorosa (non-Strict mode).

Strict & non-Strict mode

 Javascript non obbliga lo sviluppatore a dichiarare le variabili. La dichiarazione della variabile mediante la clausola var è sicuramente una buona abitudine ma non indispensabile.

var primaVarabile = 10;
secondaVariabile = 15;

Nonostante “secondaVariabile” non è stata creata mediante l’utilizzo di var, l’interprete Javascript creerà ugualmente una variabile globale di nome “secondaVariabile” senza produrre alcun avviso di errore.

Da un punto di vista può essere una comodità ma potrebbe rivelarsi un’arma a doppio taglio in quanto questa tolleranza potrebbe portare lo sviluppatore ad introdurre errori nel codice rendendo più complesse le attività di debug.

Può essere quindi utile fare ricorso al cosidetto strict mode, ovvero attivare per l’interprete Javascript una sorta tolleranza a livello zero. Tale possibilità è stata introdotta con JavaScript ECMAScript version 5 e prevede l’inserimento di una semplice stringa di testo all’inizio dello script.

"use strict";

var primaVarabile = 10;
var secondaVariabile = 15;

E’ anche possibile limitare l’utilizzo della “Strict mode” esclusivamente all’interno di una funzione:

function miaFunzione() {
  "use strict";
  var variabile = 10;
  document.write(variabile);    
}

Conseguenzialmente se utilizziamo “use strict” nel contesto globale, la sua azione si riverserà su tutto il codice; Mentre se lo utilizziamo all’interno di una funzione, la sua azione, si riverserà all’interno ed esclusivamente nella funzione stessa.

Note: use strict non è un comando vero e proprio ma un literal expression (una stringa di testo) e che il suo effetto verrà prodotto solo sui browser che incorporano versioni recenti del motore Javascript.

this e i diversi contesti

Come precedentemente detto this cambia riferimento a seconda di vari contesti; raggruppiamo qui i vari comportamenti per poi analizzarli:

this da solo all’interno del contesto globalethis si riferisce all’oggetto globale
this all’interno di una funzionethis si riferisce all’oggetto globale
this all’interno di una funzione con Strict modethis è undefined
this all’interno di un metodothis si riferisce all’oggetto proprietari del metodo
this all’interno di una funzione di callbackthis deve essere specificato con i metodi .call() .apply() e .blind()
this all’interno delle arrow functions
this in un eventothis si riferisce all’elemento che riceve l’evento

this nel contesto globale

document.write(this == window);

Nel contesto globale this fa riferimento all’oggetto globale che è l’oggetto window del browser web.
Nel procedente esempio abbiamo chiesto di stampare a video il risultato, vero o falso, richiamando this (in un contesto globale) e verificando che sia uguale a windows; il risultato sarà true.

this.nuovaProprieta = 10;
document.write(window.nuovaProprieta);

Una ulteriore riprova l’abbiamo creando una nuova proprietà “nuovaProprieta” sempre attraverso this e stampando per verifica il valore di “window.nuovaProprieta”; ovviamente, otterremo 10.

this all’interno di una funzione

all’interno di una funzione semplice

function nuovaFunzione() {
   document.write(this === window); // Otterremo true
}

All’interno di una dichiarazione di una nuova funzione this farà riferimento sempre all’oggetto globale windows.

all’interno di una funzione con Strict mode

"use strict";
function nuovaFunzione() {
   document.write(this === window); // Otterremo true
}

All’interno di una funzione, la dove si sia indicata la “Strict mode”, sia a livello globale sia all’interno della funzione stessa, this sarà impostata su undefined.

Note: Qualora impostata la "Strict mode" all'interno della funzione, essa si applica sia alla funzione che alle funzioni interne alla funzione.

all’interno di un costruttore

function automobile(brand) {
    this.brand = brand;
}

In precedenza abbiamo affrontato l’argomento “Costruttori” ovvero “l’Object Constructor”; sappiamo bene che in realtà si tratta di una funzione e saremmo quindi portati a pensare che in questo caso, this, farebbe, come per le funzioni semplici, riferimento all’oggetto globale window; in realtà non è cosi.

Quando invochiamo il nostro costruttore mediante l’istruzione “new” JavaScript crea un nuovo oggetto e imposta this all’oggetto appena creato.

Note: se omettiamo l'operatore new all'invocazione del costruttore otterremo valore undefined.

this all’interno di un metodo

var nuovoOggetto = {
    proprietaOggetto: "valore",
    metodoOggetto: function () {
        return this.proprietaOggetto;
    }
};

In questo contesto this si riferisce all’oggetto proprietario del metodo; ricordiamo che una funzione all’interno di una proprietà di un oggetto è chiamato metodo.

this all’interno di una funzione di callback

Prendiamo come esempio il metodo “mostraNomeCompleto” dell’oggetto “Persona”; il metodo, contiene all’suo interno le parole “this” che nel contesto dell’oggetto fanno riferimento all’oggetto stesso.

var persona = {
 nome: "Mario",
 cognome: "Rossi",
 mostraNomeCompleto: function () {
  return this.nome + " " + this.cognome;
 }
}

Nel caso di una callback dove richiamiamo il suddetto metodo all’interno di un’altra funzione, this, non farà più riferimento all’oggetto in quanto il suo contesto d’esecuzione è cambiato. Restituirà quindi il valore “undefined”.

function saluta(callback) {
return "Buongiorno " + callback();
}
saluta(persona.mostraNomeCompleto);

Per risolvere questa problematica potremo utilizzare uno dei seguenti metodi:

.call()Permette di invocare una funzione impostando il primo parametro come oggetto di riferimento per this
.apply()Simile a .call() prevede due parametri: il primo è l’oggetto da associare a this mentre il secondo parametro è un array dei valori da passare alla funzione
.blind()Permette di indicare al momento dell’invocazione il this di riferimento

In Javascript le funzioni sono oggetti di prima classe; ciò significa che le funzioni sono oggetti istanze di function.
Function, in quanto oggetto, ha a disposizione due metodi call() e apply() che consentono di impostare il valore di this al momento della chiamata.

.call()
var oggetto = {
x: 10
}

function nuovaFunzione(y){
return this.x + y;
}

var risultato = nuovaFunzione.call(oggetto, 10);
document.write(risultato);

Il seguente metodo accetta come primo argomento il valore di this e come secondo parametro, se è previsto, il valore da passare alla funzione.

Se non avessimo utilizzato il metodo call() in “nuovaFunzione.call(oggetto, 10);” in cui abbiamo indicato il valore di this, this, all’interno della funzione “return this.x + y;”, avrebbe avuto come riferimento, l’oggetto globale o valore undefined.

Quindi il metodo call() ci permette di indicare il riferimento di this e il parametro o i parametri da passare alla funzione.

.apply()

Il metodo apply() è simile al metodo call() unica differenza è che il suo secondo argomento è un array di argomenti.

var risultato = nuovaFunzione.apply(oggetto, [1,2,3]);
.bind()

Il metodo bind() dell’oggetto Function consente di creare una nuova funzione la cui this è impostata su un valore specificato:

var nuovaVariabile = nuovoOggetto.metodoOggetto.bind(nuovoOggetto);
document.write(nuovaVariabile());

Più semplicemente, bind() forza la funzione ad utilizzare un parametro specifico come valore di this.

this nelle Arrow functions

A differenza delle comuni funzioni dove abbiamo visto che this fa riferimento all’oggetto globale, nelle funzioni-freccia, il valore di this viene cercato da prima nello scope corrente e se non trovato, successivamente lo ricerca nello scope contenitore.

var x = 5;

var nuovaFunzione = ()=> {
var x = 10;
var y = 15;
return this.x + y;
}

In questo caso “this.x” prederà la x con valore 10.

var x = 5;

var nuovaFunzione = ()=> {
var y = 15;
return this.x + y;
}

Rimuovendo la “x” all’interno della funzione “this.x” non troverà il valore nello scope corrente della funzione e prenderà la “x” dall’oggetto globale.

this nei gestori di eventi html

<button onclick="this.style.display='none'">Clicca per rimuovere</button>

Nei gestori di eventi HTML,  this si riferisce all’elemento HTML che ha ricevuto l’evento.

Lascia un commento

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