La parola chiave this
si riferisce al valore dell'oggetto associato alla funzione al momento della chiamata, il che significa che il suo valore è diverso a seconda che la funzione venga chiamata come metodo, come funzione autonoma o come costruttore.
Quando una funzione viene chiamata, questa crea un'istanza della parola chiave this
dietro le quinte come riferimento all'oggetto che contiene la funzione, dando accesso alle proprietà e ai metodi definiti insieme ad essa dall'ambito del suo ambito.
L'utilizzo di this
è simile sotto alcuni aspetti rispetto all'uso di una variabile dichiarata
con const
. Come nel caso di una costante, this
non può essere rimosso e il suo valore non può essere
riassegnato, ma i metodi e le proprietà dell'oggetto contenente la parola chiave this
possono essere modificati.
Associazione globale
Al di fuori di una funzione o del contesto di un oggetto, this
fa riferimento alla proprietà globalThis
, che è un riferimento all'oggetto globale nella maggior parte degli ambienti JavaScript. Nel contesto di uno script eseguito in un browser web,
l'oggetto globale è l'oggetto window
:
this;
> Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, ...}
In Node.js, globalThis
è l'oggetto global
:
$ node
Welcome to Node.js v20.10.0.
Type ".help" for more information.
> this
<ref *1> Object [global] {
...
}
Al di fuori della modalità rigida, this
si riferisce anche all'oggetto globale all'interno di una funzione autonoma, perché l'oggetto principale Window
è l'oggetto che "possiede" effettivamente queste funzioni.
function myFunction() {
console.log( this );
}
myFunction();
> Window {...}
(function() {
console.log( this );
}());
> Window {...}
Quando utilizzi la modalità restrittiva, this
ha un valore undefined
all'interno di una funzione
autonoma:
(function() {
"use strict";
console.log( this );
}());
> undefined
Prima dell'introduzione della modalità rigorosa, un valore null
o undefined
per this
veniva sostituito da un riferimento all'oggetto globale. A volte potresti vedere l'associazione globale definita "associazione predefinita" a causa di questo comportamento precedente.
Associazione implicita
Quando una funzione viene chiamata come metodo di un oggetto, un'istanza di this
all'interno di questo metodo fa riferimento all'oggetto che contiene il metodo, dando accesso ai metodi e alle proprietà associati:
let myObject = {
myValue: "This is my string.",
myMethod() {
console.log( this.myValue );
}
};
myObject.myMethod();
> "This is my string."
Potrebbe sembrare che il valore di this
dipenda da come sono definiti una funzione e l'oggetto che lo contiene. Invece, il contesto per il valore di this
è
l'attuale contesto di esecuzione. In questo caso, il contesto di esecuzione indica che l'oggetto myObject
chiama il metodo myMethod
, quindi myObject
è il valore di this
. Potrebbe sembrare un aspetto tecnico nel contesto degli esempi precedenti, ma per usi più avanzati di this
è una distinzione essenziale da tenere a mente.
In generale, utilizza this
in modi che non si aspettano che il codice circostante abbia
una struttura particolare. L'eccezione a questa regola è rappresentata dalle
funzioni a freccia ES5.
this
in funzioni freccia
Nelle funzioni a freccia,
this
si risolve in un'associazione in un
ambiente circostante. Ciò significa che this
in una funzione freccia fa riferimento al valore di this
nel contesto più vicino di quella funzione:
let myObject = {
myMethod() { console.log( this ); },
myArrowFunction: () => console.log( this ),
myEnclosingMethod: function () {
this.myArrowFunction = () => { console.log(this) };
}
};
myObject.myMethod();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }
myObject.myArrowFunction();
> Window {...}
Nell'esempio precedente, myObject.myMethod()
registra myObject
come l'oggetto "possiede" quel metodo, ma myObject.myArrowFunction()
restituisce globalThis
(o undefined
), perché l'istanza di this
all'interno della funzione freccia fa riferimento invece all'ambito di inclusione più alto.
Nell'esempio seguente, myEnclosingMethod
crea una funzione freccia sull'oggetto che la contiene quando viene eseguito. L'istanza di this
all'interno della funzione freccia ora fa riferimento al valore di this
all'interno dell'ambiente che le include, ovvero il metodo che contiene la funzione freccia. Poiché il
valore di this
in myEnclosingMethod
fa riferimento a myObject
, dopo
aver definito la funzione freccia, this
all'interno della funzione freccia fa riferimento anche a
myObject
:
let myObject = {
myMethod() { console.log( this ); },
myEnclosingMethod: function () {
this.myArrowFunction = () => { console.log(this) };
}
};
myObject.myEnclosingMethod();
myObject.myArrowFunction();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }
Associazione esplicita
L'associazione implicita gestisce la maggior parte dei casi d'uso per l'uso di this
. Tuttavia, a volte potrebbe essere necessario il valore di this
per rappresentare un contesto di esecuzione specifico, anziché il contesto presunto. Un esempio illustrativo, anche se leggermente obsoleto, funziona con this
nella funzione di callback di un setTimeout
, perché questo callback ha un contesto di esecuzione univoco:
var myObject = {
myString: "This is my string.",
myMethod() {
console.log( this.myString );
}
};
myObject.myMethod();
> "This is my string."
setTimeout( myObject.myMethod, 100 );
> undefined
Sebbene questo difetto specifico di setTimeout
sia stato risolto da altre funzionalità, problemi simili di "perdere" this
sono stati precedentemente risolti creando un riferimento esplicito al valore di this
nell'ambito del contesto previsto. A volte potresti notare che le istanze this
vengono assegnate a una variabile utilizzando identificatori come that
, self
o _this
nei codebase legacy. Queste sono convenzioni comuni per gli identificatori per le variabili contenenti un valore this
passato.
Quando chiami una funzione utilizzando i metodi call()
, bind()
o apply()
,
this
fa riferimento esplicito all'oggetto che viene chiamato:
let myFunction = function() {
console.log( this.myValue );
}
let myObject = {
"myValue" : "This is my string."
};
myFunction.call( myObject );
> "This is my string."
var myObject = {
myString: "This is my string.",
myMethod() {
console.log( this.myString );
}
};
setTimeout( myObject.myMethod.bind( myObject ), 100 );
> "This is my string."
L'associazione esplicita sostituisce il valore this
fornito dall'associazione implicita.
let myObject = {
"myValue" : "This string sits alongside myMethod.",
myMethod() {
console.log( this.myValue );
}
};
let myOtherObject = {
"myValue" : "This is a string in another object entirely.",
};
myObject.myMethod.call( myOtherObject );
> "This is a string in another object entirely."
Se una funzione viene chiamata in un modo che imposti il valore di this
su
undefined
o null
, tale valore viene sostituito da globalThis
al di fuori della modalità
restrittiva:
let myFunction = function() {
console.log( this );
}
myFunction.call( null );
> Window {...}
Analogamente, se una funzione viene chiamata in un modo che dia a this
un valore primitivo, questo valore viene sostituito con l'oggetto wrapper del valore primitivo al di fuori della modalità restricted:
let myFunction = function() {
console.log( this );
}
let myNumber = 10;
myFunction.call( myNumber );
> Number { 10 }
In modalità restrittiva, un valore this
passato non viene forzato in alcun modo a un oggetto, anche se si tratta di un valore primitivo, null
o undefined
:
"use strict";
let myFunction = function() {
console.log( this );
}
let myNumber = 10;
myFunction.call( myNumber );
> 10
myFunction.call( null );
> null
Associazione di new
Quando viene utilizzata una classe come costruttore con la parola chiave new
, this
si riferisce all'istanza appena creata:
class MyClass {
myString;
constructor() {
this.myString = "My string.";
}
logThis() {
console.log( this );
}
}
const thisClass = new MyClass();
thisClass.logThis();
> Object { myString: "My string." }
Allo stesso modo, il valore di this
all'interno di una funzione del costruttore chiamata utilizzando new
fa riferimento all'oggetto che viene creato:
function MyFunction() {
this.myString = "My string.";
this.logThis = function() {
console.log( this );
}
}
const myObject = new MyFunction();
myObject.logThis();
> Object { myString: "My string.", logThis: logThis() }
Associazione gestore di eventi
Nel contesto dei gestori di eventi, il valore di this
fa riferimento all'oggetto che lo richiama. All'interno della funzione di callback di un gestore di eventi, this
fa riferimento all'elemento associato al gestore:
let button = document.querySelector( "button" );
button.addEventListener( "click", function( event ) { console.log( this ); } );
Quando un utente interagisce con button
nello snippet precedente, il risultato è
l'oggetto elemento contenente lo stesso <button>
:
> Button {}
Quando una funzione freccia viene utilizzata come callback del listener di eventi, il valore di this
viene nuovamente fornito dal contesto di esecuzione più vicino. Al livello principale, significa che this
all'interno di una funzione di callback del gestore di eventi è globalThis
(o undefined
, in modalità con restrizioni):
let button = document.querySelector( "button" );
button.addEventListener( "click", ( event ) => { console.log( this ); } );
> undefined
Come per qualsiasi altro oggetto, quando utilizzi i metodi call()
, bind()
o apply()
per fare riferimento alla funzione di callback di un listener di eventi, this
fa riferimento all'oggetto in modo esplicito:
let button = document.querySelector( "button" );
let myObject = {
"myValue" : true
};
function handleClick() {
console.log( this );
}
button.addEventListener( "click", handleClick.bind( myObject ) );
> Object { myValue: true }
Verifica le tue conoscenze
Per uno script eseguito in un browser web, qual è l'oggetto globale a cui this
fa riferimento se utilizzato al di fuori di una funzione o nel contesto di un oggetto?
window
browser
undefined