Questo articolo richiede una revisione stilistica. Scopri come puoi essere d’aiuto.`
Questa traduzione è incompleta. Collabora alla traduzione di questo articolo dall’originale in lingua inglese.
La keyword di funzione this
si comporta in modo leggermente differente in JavaScript rispetto ad altri linguaggi. Esistono inoltre alcune differenze tra strict mode e non-strict mode.
Nella maggior parte dei casi, il valore di this
è determinato da come la funzione viene invocata (chiamata). Il valore di this
non può essere impostato per assegnamento durante l'esecuzione, e potrebbe essere differente ogni volta in cui la funzione viene chiamata. ES5 ha introdotto il metodo bind
per impostare il valore di this
indipendentemente da come la funzione è invocata. ECMAScript 2015 ha introdotto le funzione a freccia ( arrow function ), in cui la keyword this
viene lessicalmente incorporata nello scope corrente ( lo scope
del contesto di esecuzione relativo al blocco corrente ).
Sintassi
this
Contesto Globale
Nel contesto di esecuzione globale (fuori da qualsiasi funzione), this
si riferisce all'oggetto globale, sia che ci si trovi in strict mode, sia che ci si trovi in non-strict mode.
console.log(this.document === document); // true // In web browsers, the window object is also the global object: console.log(this === window); // true this.a = 37; console.log(window.a); // 37
Contesto di funzione
All'interno di una funzione, il valore di this
dipende da come la funzione è invocata.
Chiamata semplice
function f1(){ return this; } f1() === window; // global object
In questo caso, il valore di this
non viene impostato dalla chiamata. Visto che il codice non è in strict mode, il valore di this
deve sempre essere un oggetto quindi viene impostato di default sull'oggetto globale.
function f2(){ "use strict"; // see strict mode return this; } f2() === undefined;
In strict mode, il valore di this
rimane impostato sul valore definito al momento dell'ingresso nel contesto di esecuzione. Se non è definito, resta undefined. Può anche essere impostato a qualsiasi valore, come null
o 42
o "I am not this"
.
this
dovrebbe essere undefined
, perchè f2
viene invocata senza specificare alcuna base (per esempio, window.f2()
). Alcuni browser non hanno implementato questo orientamento, quando hanno deciso di supportare lo strict mode. Come risultato, questi browser restituivano, in modo non corretto, l'oggetto window
.Funzioni Arrow
Nelle funzioni arrow, this
è assegnato lessicalmente, assume cioè il valore del contesto di esecuzione che contiene this.
In codice globale punta all'oggetto globale:
var globalObject = this;
var foo = (() => this);
console.log(foo() === globalObject); // true
Non importa come foo
sia invocato, this
punterà all'oggetto globale. Questo è ancora valido se è chiamato come metodo di un oggetto (che solitamente punterebbe il valore di this
sullo stesso) tramite chiamate dei metodi call
o apply
o bind
// Call as a method of an object
var obj = {foo: foo};
console.log(obj.foo() === globalObject); // true
// Attempt to set this using call
console.log(foo.call(obj) === globalObject); // true
// Attempt to set this using bind
foo = foo.bind(obj);
console.log(foo() === globalObject); // true
in ogni caso il valore di this all'interno di foo è impostato al valore di quando è stato creato (nell'esempio di sopra, l'oggetto globale). Lo stesso si applica per funzioni arrow create all'interno di altre funzioni: il loro valore di this è impostato a quello del contesto di esecuzione esterno.
// Create obj with a method bar that returns a function that
// returns its this. The returned function is created as
// an arrow function, so its this is permanently bound to the
// this of its enclosing function. The value of bar can be set
// in the call, which in turn sets the value of the
// returned function.
var obj = { bar : function() {
var x = (() => this);
return x;
}
};
// Call bar as a method of obj, setting its this to obj
// Assign a reference to the returned function to fn
var fn = obj.bar();
// Call fn without setting this, would normally default
// to the global object or undefined in strict mode
console.log(fn() === obj); // true
Nel codice sopra, la funzione (chiamiamola funzione anonima A) assegnata a obj.bar restituisce un altra funzione (chiamiamola funzione anonima B) che viene creata come funzione arrow. Il risultato, è che this della funzione B è impostata permanentemente al valore di this di obj.bar (funzione A) quando viene chiamata. quando la funzione restituita (B) viene chiamata, il relativo this sarà sempre impostato al valore di partenza. Nel codice di esempio il this della funzione B è impostato al valore this della funzione A che è obj, pertanto resta impostato ad obj anche quando viene chiamato in un modo che imposterebbe this come undefined od oggetto globale (o qualunque altro metodo, come nel precedente esempio, nel contesto di esecuzione globale).
In the above, the function(call it anonymous function A) assigned to obj.bar
returns another function(call it anonymous function B) that is created as an arrow function. As a result, function B's this
is permanently set to the this
of obj.bar
(function A)when called. When the returned function(function B) is called, its this
will always be what it was set to initially. In the above code example, function B's this
is set to function A's this
which is obj, so it remains set to obj
even when called in a manner that would normally set its this
to undefined
or the global object (or any other method as in the previous example in the global execution context).
Come metodo di un oggetto
Quando una funzione viene invocata come metodo di un oggetto, il this
, all'interno della funzione, viene impostato sull'oggetto di cui la funzione è metodo.
Nell'esempio seguente, quando o.f()
viene invocata, all'interno della funzione this
è associato all'oggetto o
.
var o = { prop: 37, f: function() { return this.prop; } }; console.log(o.f()); // logs 37
Da notare che questo comportamento non è per nulla influenzato dal come e dal dove la funzione sia stata definita. Nell'esempio precedente, abbiamo definito la funzione inline, come membro f
, nel corso della definizione di o
. Tuttavia, avremmo potuto facilmente definire la funzione prima, per poi associarla a o.f
. Il risultato sarebbe stato lo stesso:
var o = {prop: 37}; function independent() { return this.prop; } o.f = independent; console.log(o.f()); // logs 37
Questo dimostra che la cosa più importante è che la funzione venga invocata dal membro f
di o
.
In modo analogo, l'associazione di this
è influenzata solo dal membro più vicino. Nell'esempio seguente, quando invochiamo la funzione, la invochiamo come metodo g
dell'oggetto o.b
. Questa volta, durante l'esecuzione, this
, all'interno della funzione, sarà associata ad o.b
. Il fatto che l'oggetto sia, esso stesso, un membro di o
non ha alcuna conseguenza; la sola cosa che conti è il riferimento più immediato.
o.b = {g: independent, prop: 42}; console.log(o.b.g()); // logs 42
this
nella prototype chain dell'oggetto
La stessa notazione è valida per i metodi definiti altrove nella prototype chain dell'oggetto. Se il metodo è sulla prototype chain di un oggetto, this
si riferisce all'oggetto su cui il metodo è stato chiamato, come se il metodo appartenesse all'oggetto.
var o = {f:function(){ return this.a + this.b; }}; var p = Object.create(o); p.a = 1; p.b = 4; console.log(p.f()); // 5
in questo esempio, l'oggetto assegnato alla variabile p
non ha definita una proprietà f
, la eredita dal suo prototipo. Non ha importanza che il controllo per f
trovi eventualmente un membro con quel nome in o
; il controllo è cominciato con un riferimento a p.f
, quindi this all'interno della funzione assume il valore dell'oggetto a cui p
si riferisce. Cioè, dal momento che f
è chiamata come metodo di p
, la parola chiave this
al suo interno si riferisce a p
. Questa è una interessante caratteristica dell'ereditarietà dei prototipi di javascript.
this
all'interno di metodi getter o setter
Ancora, la stessa notazione è valida quando una funzione è invocata all'interno di metodi get o set. In una funzione usata come getter o setter this
viene collegata all'oggetto dal quale la proprietà è settata o ricavata.
function modulus(){ return Math.sqrt(this.re * this.re + this.im * this.im); } var o = { re: 1, im: -1, get phase(){ return Math.atan2(this.im, this.re); } }; Object.defineProperty(o, 'modulus', { get: modulus, enumerable:true, configurable:true}); console.log(o.phase, o.modulus); // logs -0.78 1.4142
Come costruttore
Quando una funzione è usata come un costruttore (tramite la parola chiave new
), this
è collegata al nuovo oggetto che viene costruito.
Nota: mentre di default un costruttore restituisce l'oggetto riferenziato da this
, può invece restituire qualche altro oggetto (se il valore di ritorno non è un oggetto, allora viene restituito l'oggetto this
).
/* * Constructors work like this: * * function MyConstructor(){ * // Actual function body code goes here. * // Create properties on |this| as * // desired by assigning to them. E.g., * this.fum = "nom"; * // et cetera... * * // If the function has a return statement that * // returns an object, that object will be the * // result of the |new| expression. Otherwise, * // the result of the expression is the object * // currently bound to |this| * // (i.e., the common case most usually seen). * } */ function C(){ this.a = 37; } var o = new C(); console.log(o.a); // logs 37 function C2(){ this.a = 37; return {a:38}; } o = new C2(); console.log(o.a); // logs 38
Nell'ultimo esempio (C2)
, dal momento che è stato restituito un oggetto durante la costruzione, il nuovo oggetto a cui this
era collegato viene semplicemente scartato. (Questo rende essenzialmente l'assegnazione "this.a = 37;
" codice inutile. Non lo è in senso stretto, in quanto viene eseguito, ma può essere eliminato senza conseguenze).
I metodi call
e apply
Dove una funzione usa la parola chiave this
, il suo valore può essere collegato ad un qualsivoglia oggetto nella chiamata usando i metodi call
o apply
che tutte le funzioni ereditano da Function.prototype
.
function add(c, d){ return this.a + this.b + c + d; } var o = {a:1, b:3}; // The first parameter is the object to use as // 'this', subsequent parameters are passed as // arguments in the function call add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16 // The first parameter is the object to use as // 'this', the second is an array whose // members are used as the arguments in the function call add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34
Notare che con call
e apply
, se il valore passato tramite this
non è un oggetto, viene eseguito un tentativo di convertire tale valore in oggetto usando l'operazione interna ToObject
. pertanto, se il valore passato è un primitivo come 7 o 'foo', questo verrà convertito ad Object
usando il relativo costruttore, quindi il valore primitivo 7
viene convertito come new
Number(7)
e la stringa 'foo'
viene convertita come new String('foo')
, per esempio:
function bar() { console.log(Object.prototype.toString.call(this)); } bar.call(7); // [object Number]
Il metodo bind
ECMAScript 5 ha introdotto Function.prototype.bind
. Chiamare f.bind(someObject)
crea una nuova funzione con lo stesso corpo e visibità di f,
ma nella funzione originale si trova la parola chiave this
, nella nuova funzione viene permanentemente collegato al primo argomento passato alla chiamata del metodo bind
, ignorando come la funzione stessa venga usata.
function f(){ return this.a; } var g = f.bind({a:"azerty"}); console.log(g()); // azerty var o = {a:37, f:f, g:g}; console.log(o.f(), o.g()); // 37, azerty
Come handler degli eventi del DOM
Quando una funzione viene usata come handler di eventi, i suoi riferimenti this
sono puntati all'elemento che ha originato l'evento (alcuni Browser non seguono queste convenzioni per i listeners agguinti dinamicamente tramite metodi diversi da addEventListener
).
// When called as a listener, turns the related element blue function bluify(e){ // Always true console.log(this === e.currentTarget); // true when currentTarget and target are the same object console.log(this === e.target); this.style.backgroundColor = '#A5D9F3'; } // Get a list of every element in the document var elements = document.getElementsByTagName('*'); // Add bluify as a click listener so when the // element is clicked on, it turns blue for(var i=0 ; i<elements.length ; i++){ elements[i].addEventListener('click', bluify, false); }
In un handler di eventi "in-line"
quando il codice è chiamato da un handler in-line, this
punta all'elemento DOM sul quale il listener è posizionato:
When code is called from an in–line handler, its this
is set to the DOM element on which the listener is placed:
<button onclick="alert(this.tagName.toLowerCase());"> Show this </button>
Sopra, alert
mostra 'button
'. Notare comunque che this assume tale valore solo al di fuori di una funzione:
<button onclick="alert((function(){return this}()));"> Show inner this </button>
in questo caso, nella funzione interna, this
non punta all'elemento DOM quindi restituisce l'oggetto globale/window (cioè l'oggetto di default in modalità non-strict, in cui this
non viene impostato dalla chiamata)
Specifiche
Specification | Status | Comment |
---|---|---|
ECMAScript 2017 Draft (ECMA-262) The definition of 'The this keyword' in that specification. |
Draft | |
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'The this keyword' in that specification. |
Standard | |
ECMAScript 5.1 (ECMA-262) The definition of 'The this keyword' in that specification. |
Standard | |
ECMAScript 3rd Edition (ECMA-262) The definition of 'The this keyword' in that specification. |
Standard | |
ECMAScript 1st Edition (ECMA-262) The definition of 'The this keyword' in that specification. |
Standard | Initial definition. Implemented in JavaScript 1.0. |
Compatibilità dei browser
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Basic support | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) |
Feature | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
Basic support | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) |
Vedere Anche
- Strict mode
- All this, un articolo su
this
in diversi contesti (Inglese) - Semplice spiegazione della parola chiave 'this' in JavaScript (inglese)