Como funciona a palavra-chave “this”?

Jun 27 2010

Percebi que não parece haver uma explicação clara do que é a thispalavra-chave e como ela é usada correta (e incorretamente) em JavaScript no site Stack Overflow.

Testemunhei um comportamento muito estranho com ele e não consegui entender por que ocorreu.

Como thisfunciona e quando deve ser usado?

Respostas

1378 DanielTrebbien Jun 27 2010 at 20:15

Recomendo a leitura do artigo Scope in JavaScript ( mirror ) de Mike West primeiro. É uma introdução excelente e amigável aos conceitos e cadeias de escopo em JavaScript.this

Depois que você começar a se acostumar this, as regras serão bem simples. O padrão ECMAScript 5.1 define this:

§11.1.1 A thispalavra-chave

A thispalavra-chave avalia o valor de ThisBinding do contexto de execução atual

ThisBinding é algo que o interpretador JavaScript mantém enquanto avalia o código JavaScript, como um registro de CPU especial que contém uma referência a um objeto. O interpretador atualiza o ThisBinding sempre que estabelece um contexto de execução em um de apenas três casos diferentes:

1. Contexto de execução global inicial

Este é o caso do código JavaScript que é avaliado no nível superior, por exemplo, quando diretamente dentro de <script>:

<script>
  alert("I'm evaluated in the initial global execution context!");

  setTimeout(function () {
      alert("I'm NOT evaluated in the initial global execution context.");
  }, 1);
</script>

Ao avaliar o código no contexto de execução global inicial, ThisBinding é definido como o objeto global, window( §10.4.1.1 ).

2. Inserindo o código de avaliação

  • … Por uma chamada direta para eval()ThisBinding é deixado inalterado; é o mesmo valor que ThisBinding do contexto de execução de chamada ( §10.4.2 (2) (a)).

  • … Se não por uma chamada direta para eval()
    ThisBinding é definido para o objeto global como se estivesse executando no contexto de execução global inicial ( §10.4.2 (1)).

§15.1.2.1.1 define o que é uma chamada direta para eval(). Basicamente, eval(...)é uma chamada direta, enquanto algo parecido com (0, eval)(...)ou var indirectEval = eval; indirectEval(...);é uma chamada indireta para eval(). Veja a resposta de chuckj para (1, eval) ('this') vs eval ('this') em JavaScript? e o ECMA-262-5 de Dmitry Soshnikov em detalhes. Capítulo 2. Modo estrito. para quando você pode usar uma eval()chamada indireta .

3. Inserindo o código de função

Isso ocorre ao chamar uma função. Se uma função é chamada em um objeto, como in obj.myMethod()ou equivalente obj["myMethod"](), ThisBinding é definido para o objeto ( objno exemplo; §13.2.1 ). Na maioria dos outros casos, ThisBinding é definido como o objeto global ( §10.4.3 ).

O motivo para escrever "na maioria dos outros casos" é porque existem oito funções integradas ECMAScript 5 que permitem que ThisBinding seja especificada na lista de argumentos. Essas funções especiais assumem uma chamada thisArgque se torna ThisBinding ao chamar a função ( §10.4.3 ).

Essas funções internas especiais são:

  • Function.prototype.apply( thisArg, argArray )
  • Function.prototype.call( thisArg [ , arg1 [ , arg2, ... ] ] )
  • Function.prototype.bind( thisArg [ , arg1 [ , arg2, ... ] ] )
  • Array.prototype.every( callbackfn [ , thisArg ] )
  • Array.prototype.some( callbackfn [ , thisArg ] )
  • Array.prototype.forEach( callbackfn [ , thisArg ] )
  • Array.prototype.map( callbackfn [ , thisArg ] )
  • Array.prototype.filter( callbackfn [ , thisArg ] )

No caso das Function.prototypefunções, elas são chamadas em um objeto de função, mas em vez de definir ThisBinding como o objeto de função, ThisBinding é definido como thisArg.

No caso das Array.prototypefunções, o dado callbackfné chamado em um contexto de execução onde ThisBinding é definido como thisArgse fornecido; caso contrário, para o objeto global.

Essas são as regras para JavaScript simples. Quando você começa a usar bibliotecas JavaScript (por exemplo, jQuery), você pode descobrir que certas funções de biblioteca manipulam o valor de this. Os desenvolvedores dessas bibliotecas JavaScript fazem isso porque tende a oferecer suporte aos casos de uso mais comuns e os usuários da biblioteca geralmente consideram esse comportamento mais conveniente. Ao passar funções de retorno de chamada que fazem referência thisa funções de biblioteca, você deve consultar a documentação para obter quaisquer garantias sobre qual é o valor de thisquando a função é chamada.

Se você está se perguntando como uma biblioteca JavaScript manipula o valor de this, a biblioteca está simplesmente usando uma das funções JavaScript integradas que aceitam a thisArg. Você também pode escrever sua própria função tomando uma função de retorno de chamada e thisArg:

function doWork(callbackfn, thisArg) {
    //...
    if (callbackfn != null) callbackfn.call(thisArg);
}

Há um caso especial que ainda não mencionei. Ao construir um novo objeto por meio do newoperador, o interpretador JavaScript cria um novo objeto vazio, define algumas propriedades internas e, a seguir, chama a função construtora no novo objeto. Assim, quando uma função é chamada em um contexto de construtor, o valor de thisé o novo objeto que o interpretador criou:

function MyType() {
    this.someData = "a string";
}

var instance = new MyType();
// Kind of like the following, but there are more steps involved:
// var instance = {};
// MyType.call(instance);

Funções de seta

As funções de seta (introduzidas no ECMA6) alteram o escopo de this. Veja a pergunta canônica existente, função de seta vs declaração / expressões de função: são equivalentes / trocáveis? Para maiores informações. Mas resumindo:

As funções de seta não têm sua própria this.... vinculação. Em vez disso, esses identificadores são resolvidos no escopo léxico como qualquer outra variável. Isso significa que dentro de uma função de seta, this... referem-se aos valores de thisno ambiente em que a função de seta é definida.

Apenas por diversão, teste sua compreensão com alguns exemplos

Para revelar as respostas, passe o mouse sobre as caixas cinza claro.

  1. Qual é o valor de thisna linha marcada? Porque?

window - A linha marcada é avaliada no contexto de execução global inicial.

    if (true) {
        // What is `this` here?
    }
  1. Qual é o valor de thisna linha marcada quando obj.staticFunction()é executado? Porque?

obj - Ao chamar uma função em um objeto, ThisBinding é definido para o objeto.

var obj = {
    someData: "a string"
};

function myFun() {
    return this // What is `this` here?
}

obj.staticFunction = myFun;

console.log("this is window:", obj.staticFunction() == window);
console.log("this is obj:", obj.staticFunction() == obj);
  

  1. Qual é o valor de thisna linha marcada? Porque?

window

Neste exemplo, o interpretador JavaScript insere o código da função, mas como myFun/ obj.myMethodnão é chamado em um objeto, ThisBinding é definido como window.

Isso é diferente do Python, em que acessar um método ( obj.myMethod) cria um objeto de método vinculado .

var obj = {
    myMethod: function () {
        return this; // What is `this` here?
    }
};
var myFun = obj.myMethod;
console.log("this is window:", myFun() == window);
console.log("this is obj:", myFun() == obj);
  

  1. Qual é o valor de thisna linha marcada? Porque?

window

Este foi complicado. Ao avaliar o código de avaliação, thisé obj. No entanto, no código eval, myFunnão é chamado em um objeto, portanto, ThisBinding é definido como windowpara a chamada.

 <!-- no snippet because, seemingly, eval doesn’t work in snippets -->

    function myFun() {
        return this; // What is `this` here?
    }
    var obj = {
        myMethod: function () {
            eval("myFun()");
        }
    };
  1. Qual é o valor de thisna linha marcada? Porque?

obj

A linha myFun.call(obj);está chamando a função interna especial Function.prototype.call(), que aceita thisArgcomo o primeiro argumento.

function myFun() {
    return this; // What is `this` here?
}
var obj = {
    someData: "a string"
};
console.log("this is window:", myFun.call(obj) == window);
console.log("this is obj:", myFun.call(obj) == obj);
  

168 Mahesha999 Jul 08 2013 at 00:32

A thispalavra-chave se comporta de maneira diferente em JavaScript em comparação com outras linguagens. Em linguagens orientadas a objetos, a thispalavra - chave se refere à instância atual da classe. Em JavaScript, o valor de thisé determinado pelo contexto de invocação de function ( context.function()) e onde é chamado.

1. Quando usado em contexto global

Quando você usa thisno contexto global, é vinculado ao objeto global ( windowno navegador)

document.write(this);  //[object Window]

Quando você usa thisdentro de uma função definida no contexto global, thisainda está vinculado ao objeto global, pois a função é na verdade um método de contexto global.

function f1()
{
   return this;
}
document.write(f1());  //[object Window]

Acima f1é feito um método de objeto global. Assim, também podemos chamá-lo no windowobjeto da seguinte maneira:

function f()
{
    return this;
}

document.write(window.f()); //[object Window]

2. Quando usado dentro do método do objeto

Quando você usa uma thispalavra-chave dentro de um método de objeto, thisé vinculado ao objeto envolvente "imediato".

var obj = {
    name: "obj",
    f: function () {
        return this + ":" + this.name;
    }
};
document.write(obj.f());  //[object Object]:obj

Acima, coloquei a palavra imediato entre aspas duplas. É para deixar claro que, se você aninhar o objeto dentro de outro objeto, thisestará vinculado ao pai imediato.

var obj = {
    name: "obj1",
    nestedobj: {
        name:"nestedobj",
        f: function () {
            return this + ":" + this.name;
        }
    }            
}

document.write(obj.nestedobj.f()); //[object Object]:nestedobj

Mesmo se você adicionar função explicitamente ao objeto como um método, ainda segue as regras acima, que thisainda aponta para o objeto pai imediato.

var obj1 = {
    name: "obj1",
}

function returnName() {
    return this + ":" + this.name;
}

obj1.f = returnName; //add method to object
document.write(obj1.f()); //[object Object]:obj1

3. Ao invocar a função sem contexto

Quando você usa uma thisfunção interna que é chamada sem qualquer contexto (ou seja, não em qualquer objeto), ela é vinculada ao objeto global ( windowno navegador) (mesmo se a função for definida dentro do objeto).

var context = "global";

var obj = {  
    context: "object",
    method: function () {                  
        function f() {
            var context = "function";
            return this + ":" +this.context; 
        };
        return f(); //invoked without context
    }
};

document.write(obj.method()); //[object Window]:global 

Experimentando tudo com funções

Podemos tentar os pontos acima com funções também. No entanto, existem algumas diferenças.

  • Acima, adicionamos membros a objetos usando notação literal de objeto. Podemos adicionar membros às funções usando this. para especificá-los.
  • A notação literal de objeto cria uma instância de objeto que podemos usar imediatamente. Com a função, podemos primeiro precisar criar sua instância usando o newoperador.
  • Também em uma abordagem literal de objeto, podemos adicionar explicitamente membros a um objeto já definido usando o operador ponto. Isso é adicionado apenas à instância específica. No entanto, adicionei a variável ao protótipo da função para que ela seja refletida em todas as instâncias da função.

A seguir, experimentei todas as coisas que fizemos com Object e thisacima, mas primeiro criando uma função em vez de escrever um objeto diretamente.

/********************************************************************* 
  1. When you add variable to the function using this keyword, it 
     gets added to the function prototype, thus allowing all function 
     instances to have their own copy of the variables added.
*********************************************************************/
function functionDef()
{
    this.name = "ObjDefinition";
    this.getName = function(){                
        return this+":"+this.name;
    }
}        

obj1 = new functionDef();
document.write(obj1.getName() + "<br />"); //[object Object]:ObjDefinition   

/********************************************************************* 
   2. Members explicitly added to the function protorype also behave 
      as above: all function instances have their own copy of the 
      variable added.
*********************************************************************/
functionDef.prototype.version = 1;
functionDef.prototype.getVersion = function(){
    return "v"+this.version; //see how this.version refers to the
                             //version variable added through 
                             //prototype
}
document.write(obj1.getVersion() + "<br />"); //v1

/********************************************************************* 
   3. Illustrating that the function variables added by both above 
      ways have their own copies across function instances
*********************************************************************/
functionDef.prototype.incrementVersion = function(){
    this.version = this.version + 1;
}
var obj2 = new functionDef();
document.write(obj2.getVersion() + "<br />"); //v1

obj2.incrementVersion();      //incrementing version in obj2
                              //does not affect obj1 version

document.write(obj2.getVersion() + "<br />"); //v2
document.write(obj1.getVersion() + "<br />"); //v1

/********************************************************************* 
   4. `this` keyword refers to the immediate parent object. If you 
       nest the object through function prototype, then `this` inside 
       object refers to the nested object not the function instance
*********************************************************************/
functionDef.prototype.nestedObj = { name: 'nestedObj', 
                                    getName1 : function(){
                                        return this+":"+this.name;
                                    }                            
                                  };

document.write(obj2.nestedObj.getName1() + "<br />"); //[object Object]:nestedObj

/********************************************************************* 
   5. If the method is on an object's prototype chain, `this` refers 
      to the object the method was called on, as if the method was on 
      the object.
*********************************************************************/
var ProtoObj = { fun: function () { return this.a } };
var obj3 = Object.create(ProtoObj); //creating an object setting ProtoObj
                                    //as its prototype
obj3.a = 999;                       //adding instance member to obj3
document.write(obj3.fun()+"<br />");//999
                                    //calling obj3.fun() makes 
                                    //ProtoObj.fun() to access obj3.a as 
                                    //if fun() is defined on obj3

4. Quando usado dentro da função de construtor .

Quando a função é usada como um construtor (ou seja, quando é chamada com a newpalavra - chave), o thiscorpo da função dentro aponta para o novo objeto que está sendo construído.

var myname = "global context";
function SimpleFun()
{
    this.myname = "simple function";
}

var obj1 = new SimpleFun(); //adds myname to obj1
//1. `new` causes `this` inside the SimpleFun() to point to the
//   object being constructed thus adding any member
//   created inside SimipleFun() using this.membername to the
//   object being constructed
//2. And by default `new` makes function to return newly 
//   constructed object if no explicit return value is specified

document.write(obj1.myname); //simple function

5. Quando usado dentro da função definida na cadeia de protótipo

Se o método está na cadeia de protótipos de um objeto, thisdentro desse método se refere ao objeto em que o método foi chamado, como se o método estivesse definido no objeto.

var ProtoObj = {
    fun: function () {
        return this.a;
    }
};
//Object.create() creates object with ProtoObj as its
//prototype and assigns it to obj3, thus making fun() 
//to be the method on its prototype chain

var obj3 = Object.create(ProtoObj);
obj3.a = 999;
document.write(obj3.fun()); //999

//Notice that fun() is defined on obj3's prototype but 
//`this.a` inside fun() retrieves obj3.a   

6. Dentro das funções call (), apply () e bind ()

  • Todos esses métodos são definidos em Function.prototype.
  • Esses métodos permitem escrever uma função uma vez e invocá-la em um contexto diferente. Ou seja, permitem especificar o valor thisque será utilizado durante a execução da função. Eles também aceitam quaisquer parâmetros a serem passados ​​para a função original quando ela é chamada.
  • fun.apply(obj1 [, argsArray])Define obj1como o valor de thisdentro fun()e chama os fun()elementos de passagem de argsArraycomo seus argumentos.
  • fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- Define obj1como o valor de thisdentro fun()e chama fun()passando arg1, arg2, arg3, ...como seus argumentos.
  • fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- Retorna a referência à função funcom thisdentro do limite de diversão obj1e parâmetros de funlimite para os parâmetros especificados arg1, arg2, arg3,....
  • Até agora a diferença entre apply, calle binddeve ter se tornado aparente. applypermite especificar os argumentos para funcionar como um objeto tipo array, ou seja, um objeto com uma lengthpropriedade numérica e propriedades inteiras não negativas correspondentes. Considerando que callpermite especificar os argumentos para a função diretamente. Ambos applye callimediatamente chama a função no contexto especificado e com os argumentos especificados. Por outro lado, bindsimplesmente retorna a função associada ao thisvalor especificado e aos argumentos. Podemos capturar a referência a esta função retornada atribuindo-a a uma variável e, posteriormente, podemos chamá-la a qualquer momento.
function add(inc1, inc2)
{
    return this.a + inc1 + inc2;
}

var o = { a : 4 };
document.write(add.call(o, 5, 6)+"<br />"); //15
      //above add.call(o,5,6) sets `this` inside
      //add() to `o` and calls add() resulting:
      // this.a + inc1 + inc2 = 
      // `o.a` i.e. 4 + 5 + 6 = 15
document.write(add.apply(o, [5, 6]) + "<br />"); //15
      // `o.a` i.e. 4 + 5 + 6 = 15

var g = add.bind(o, 5, 6);       //g: `o.a` i.e. 4 + 5 + 6
document.write(g()+"<br />");    //15

var h = add.bind(o, 5);          //h: `o.a` i.e. 4 + 5 + ?
document.write(h(6) + "<br />"); //15
      // 4 + 5 + 6 = 15
document.write(h() + "<br />");  //NaN
      //no parameter is passed to h()
      //thus inc2 inside add() is `undefined`
      //4 + 5 + undefined = NaN</code>

7. thismanipuladores de eventos internos

  • Quando você atribui função diretamente a manipuladores de eventos de um elemento, o uso de thisfunção de manipulação de eventos diretamente dentro se refere ao elemento correspondente. Essa atribuição direta de função pode ser feita usando o addeventListenermétodo ou por meio dos métodos tradicionais de registro de eventos, como onclick.
  • Da mesma forma, quando você usa thisdiretamente dentro da propriedade do evento (como <button onclick="...this..." >) do elemento, ela se refere ao elemento.
  • No entanto, o uso de thisindiretamente por meio de outra função chamada dentro da função de tratamento de eventos ou propriedade de evento resolve para o objeto global window.
  • O mesmo comportamento acima é obtido quando anexamos a função ao manipulador de eventos usando o método de modelo de Registro de Eventos da Microsoft attachEvent. Em vez de atribuir a função ao manipulador de eventos (e assim tornar o método de função do elemento), ele chama a função no evento (efetivamente chamando-a no contexto global).

Eu recomendo tentar isso melhor no JSFiddle .

<script> 
    function clickedMe() {
       alert(this + " : " + this.tagName + " : " + this.id);
    } 
    document.getElementById("button1").addEventListener("click", clickedMe, false);
    document.getElementById("button2").onclick = clickedMe;
    document.getElementById("button5").attachEvent('onclick', clickedMe);   
</script>

<h3>Using `this` "directly" inside event handler or event property</h3>
<button id="button1">click() "assigned" using addEventListner() </button><br />
<button id="button2">click() "assigned" using click() </button><br />
<button id="button3" onclick="alert(this+ ' : ' + this.tagName + ' : ' + this.id);">used `this` directly in click event property</button>

<h3>Using `this` "indirectly" inside event handler or event property</h3>
<button onclick="alert((function(){return this + ' : ' + this.tagName + ' : ' + this.id;})());">`this` used indirectly, inside function <br /> defined & called inside event property</button><br />

<button id="button4" onclick="clickedMe()">`this` used indirectly, inside function <br /> called inside event property</button> <br />

IE only: <button id="button5">click() "attached" using attachEvent() </button>

8. thisna função de seta ES6

Em uma função de seta, thisse comportará como variáveis ​​comuns: será herdado de seu escopo léxico. A função this, onde a função de seta é definida, será a função de seta this.

Então, esse é o mesmo comportamento que:

(function(){}).bind(this)

Veja o seguinte código:

const globalArrowFunction = () => {
  return this;
};

console.log(globalArrowFunction()); //window

const contextObject = {
  method1: () => {return this},
  method2: function(){
    return () => {return this};
  }
};

console.log(contextObject.method1()); //window

const contextLessFunction = contextObject.method1;

console.log(contextLessFunction()); //window

console.log(contextObject.method2()()) //contextObject

const innerArrowFunction = contextObject.method2();

console.log(innerArrowFunction()); //contextObject 
66 user3459110 Oct 26 2014 at 22:07

Javascript's this

Invocação de função simples

Considere a seguinte função:

function foo() {
    console.log("bar");
    console.log(this);
}
foo(); // calling the function

Observe que estamos executando isso no modo normal, ou seja, o modo estrito não é usado.

Ao executar em um navegador, o valor de thisseria registrado como window. Isso ocorre porque windowé a variável global no escopo de um navegador da web.

Se você executar esse mesmo trecho de código em um ambiente como node.js, fará thisreferência à variável global em seu aplicativo.

Agora, se executarmos isso no modo estrito adicionando a instrução "use strict";ao início da declaração da função, thisnão faremos mais referência à variável global em nenhum dos ambientes. Isso é feito para evitar confusões no modo estrito. thisseria, neste caso, apenas log undefined, porque é isso que é, não está definido.

Nos casos a seguir, veríamos como manipular o valor de this.

Chamar uma função em um objeto

Existem diferentes maneiras de fazer isso. Se você chamou métodos nativos em Javascript como forEache slice, você já deve saber que a thisvariável nesse caso se refere ao Objectno qual você chamou essa função (observe que em javascript, quase tudo é um Object, incluindo Arrays e Functions). Veja o código a seguir, por exemplo.

var myObj = {key: "Obj"};
myObj.logThis = function () {
    // I am a method
    console.log(this);
}
myObj.logThis(); // myObj is logged

Se um Objectcontém uma propriedade que contém um Function, a propriedade é chamada de método. Este método, quando chamado, sempre terá sua thisvariável configurada para o Objectqual está associado. Isso é verdadeiro para os modos estrito e não estrito.

Observe que se um método for armazenado (ou melhor, copiado) em outra variável, a referência a thisnão será mais preservada na nova variável. Por exemplo:

// continuing with the previous code snippet

var myVar = myObj.logThis;
myVar();
// logs either of window/global/undefined based on mode of operation

Considerando um cenário mais comumente prático:

var el = document.getElementById('idOfEl');
el.addEventListener('click', function() { console.log(this) });
// the function called by addEventListener contains this as the reference to the element
// so clicking on our element would log that element itself

A newpalavra-chave

Considere uma função construtora em Javascript:

function Person (name) {
    this.name = name;
    this.sayHello = function () {
        console.log ("Hello", this);
    }
}

var awal = new Person("Awal");
awal.sayHello();
// In `awal.sayHello`, `this` contains the reference to the variable `awal`

Como é que isso funciona? Bem, vamos ver o que acontece quando usamos a newpalavra - chave.

  1. Chamar a função com a newpalavra - chave inicializaria imediatamente um Objecttipo Person.
  2. O construtor deste Objecttem seu construtor definido como Person. Além disso, observe que typeof awalretornaria Objectapenas.
  3. Este novo Objectseria atribuído ao protótipo de Person.prototype. Isso significa que qualquer método ou propriedade no Personprotótipo estaria disponível para todas as instâncias de Person, incluindo awal.
  4. A função em Personsi agora é chamada; thissendo uma referência ao objeto recém-construído awal.

Muito simples, hein?

Observe que a especificação oficial do ECMAScript em nenhum lugar afirma que esses tipos de funções são constructorfunções reais . Eles são apenas funções normais e newpodem ser usados ​​em qualquer função. Acontece que os usamos como tal, e por isso os chamamos apenas como tal.

Chamando funções em Funções: calleapply

Então sim, uma vez que functions também são Objects(e de fato variáveis ​​de primeira classe em Javascript), até mesmo funções têm métodos que são ... bem, funções em si.

Todas as funções herdam do global Function, e dois de seus muitos métodos são calle apply, e ambos podem ser usados ​​para manipular o valor de thisna função na qual são chamados.

function foo () { console.log (this, arguments); }
var thisArg = {myObj: "is cool"};
foo.call(thisArg, 1, 2, 3);

Este é um exemplo típico de uso call. Basicamente, ele pega o primeiro parâmetro e define thisa função foocomo uma referência para thisArg. Todos os outros parâmetros passados ​​para callsão passados ​​para a função foocomo argumentos.
Portanto, o código acima será registrado {myObj: "is cool"}, [1, 2, 3]no console. Uma maneira muito boa de alterar o valor de thisqualquer função.

applyé quase o mesmo que callaceitar que leva apenas dois parâmetros: thisArge um array que contém os argumentos a serem passados ​​para a função. Portanto, a callchamada acima pode ser traduzida applyassim:

foo.apply(thisArg, [1,2,3])

Observe que calle applypode substituir o valor da thisinvocação do método set by dot que discutimos no segundo item. Simples o suficiente :)

Apresentando .... bind!

bindé irmão de calle apply. É também um método herdado por todas as funções do Functionconstrutor global em Javascript. A diferença entre binde call/ applyé que ambos calle applyrealmente invocarão a função. bind, por outro lado, retorna uma nova função com o thisArge argumentspredefinido. Vamos dar um exemplo para entender melhor isso:

function foo (a, b) {
    console.log (this, arguments);
}
var thisArg = {myObj: "even more cool now"};
var bound = foo.bind(thisArg, 1, 2);
console.log (typeof bound); // logs `function`
console.log (bound);
/* logs `function () { native code }` */

bound(); // calling the function returned by `.bind`
// logs `{myObj: "even more cool now"}, [1, 2]`

Veja a diferença entre os três? É sutil, mas eles são usados ​​de forma diferente. Like calle apply, bindtambém substituirá o valor de thisdefinido pela invocação do método de ponto.

Observe também que nenhuma dessas três funções altera a função original. calle applyretornaria o valor de funções recém-construídas enquanto bindretornaria a própria função recém-construída, pronta para ser chamada.

Coisas extras, copie isto

Às vezes, você não gosta do fato de que thismuda com o escopo, especialmente o escopo aninhado. Dê uma olhada no exemplo a seguir.

var myObj = {
    hello: function () {
        return "world"
        },
    myMethod: function () {
        // copy this, variable names are case-sensitive
        var that = this;
        // callbacks ftw \o/
        foo.bar("args", function () {
            // I want to call `hello` here
            this.hello(); // error
            // but `this` references to `foo` damn!
            // oh wait we have a backup \o/
            that.hello(); // "world"
        });
    }
  };

No código acima, vemos que o valor de thismudou com o escopo aninhado, mas queríamos o valor de thisdo escopo original. Então nós 'copiado' thisa thate usou a copiar em vez de this. Inteligente, hein?

Índice:

  1. O que é retido thispor padrão?
  2. E se chamarmos a função como um método com notação de objeto-ponto?
  3. E se usarmos a newpalavra - chave?
  4. Como podemos manipular thiscom calle apply?
  5. Usando bind.
  6. Copiar thispara resolver problemas de escopo aninhado.
49 arunjitsingh Jun 27 2010 at 21:10

"isso" tem tudo a ver com escopo. Cada função tem seu próprio escopo e, como tudo em JS é um objeto, até mesmo uma função pode armazenar alguns valores em si mesma usando "this". OOP 101 ensina que "isto" só se aplica a instâncias de um objeto. Portanto, toda vez que uma função é executada, uma nova "instância" dessa função tem um novo significado de "isso".

A maioria das pessoas fica confusa quando tenta usar "this" dentro de funções de fechamento anônimas como:

(função (valor) {
    this.value = value;
    $ ('. some-elements'). each (function (elt) {
        elt.innerHTML = this.value; // uh oh !! possivelmente indefinido
    });
}) (2);

Então aqui, dentro de cada (), "isto" não contém o "valor" que você espera que (de

this.value = value;
acima dele). Então, para superar esse problema (sem trocadilhos), um desenvolvedor pode:

(função (valor) {
    var self = this; // pequena mudança
    self.value = value;
    $ ('. some-elements'). each (function (elt) {
        elt.innerHTML = self.value; // ufa !! == 2
    });
}) (2);

Experimente; você começará a gostar deste padrão de programação

18 carlodurso Oct 30 2014 at 10:58

Desde que este tópico aumentou, eu compilei alguns pontos para leitores novos no thistópico.

Como é o valor de thisdeterminado?

Usamos essa semelhante à maneira como usamos pronomes nas línguas naturais como o Inglês: “John está correndo rápido, porque ele está tentando pegar o trem.” Em vez disso, poderíamos ter escrito “… John está tentando pegar o trem”.

var person = {    
    firstName: "Penelope",
    lastName: "Barrymore",
    fullName: function () {

    // We use "this" just as in the sentence above:
       console.log(this.firstName + " " + this.lastName);

    // We could have also written:
       console.log(person.firstName + " " + person.lastName);
    }
}

this não recebe um valor até que um objeto invoque a função onde está definido. No escopo global, todas as variáveis ​​e funções globais são definidas no windowobjeto. Portanto, thisem uma função global se refere a (e tem o valor de) o windowobjeto global .

Quando use strict, thisem funções globais e anônimas que não estão vinculadas a nenhum objeto, possui um valor de undefined.

A thispalavra-chave é mais mal compreendida quando: 1) pegamos emprestado um método que usa this, 2) atribuímos um método que usa thispara uma variável, 3) uma função que usa thisé passada como uma função de retorno de chamada e 4) thisé usada dentro de uma closure - uma função interna. (2)

O que guarda o futuro

Definido no ECMA Script 6 , as funções de seta adotam a thisvinculação do escopo delimitador (função ou global).

function foo() {
     // return an arrow function
     return (a) => {
     // `this` here is lexically inherited from `foo()`
     console.log(this.a);
  };
}
var obj1 = { a: 2 };
var obj2 = { a: 3 };

var bar = foo.call(obj1);
bar.call( obj2 ); // 2, not 3!

Embora as funções de seta forneçam uma alternativa ao uso bind(), é importante observar que elas essencialmente desativam o thismecanismo tradicional em favor de um escopo léxico mais amplamente compreendido. (1)


Referências:

  1. this & Object Prototypes , de Kyle Simpson. © 2014 Getify Solutions.
  2. javascriptissexy.com - http://goo.gl/pvl0GX
  3. Angus Croll - http://goo.gl/Z2RacU
18 Seph Oct 07 2013 at 02:46

thisem JavaScript sempre se refere ao 'dono' da função que está sendo executada .

Se nenhum proprietário explícito for definido, o principal proprietário, o objeto janela, será referenciado.

Então se eu fizesse

function someKindOfFunction() {
   this.style = 'foo';
}

element.onclick = someKindOfFunction;

thisfaria referência ao objeto do elemento. Mas tenha cuidado, muitas pessoas cometem esse erro.

<element onclick="someKindOfFunction()">

No último caso, você meramente faz referência à função, não a entrega ao elemento. Portanto, thisfará referência ao objeto janela.

15 blockhead Jun 27 2010 at 20:15

Cada contexto de execução em javascript tem um este parâmetro que é definido por:

  1. Como a função é chamada (incluindo como um método de objeto, uso de call e apply , uso de new )
  2. Uso de ligação
  3. Lexicamente para funções de seta (elas adotam o this de seu contexto de execução externo)
  4. Se o código está em modo estrito ou não estrito
  5. Se o código foi invocado usando eval

Você pode definir o valor dessa usando func.call, func.applyou func.bind.

Por padrão, e o que confunde a maioria dos iniciantes, quando um ouvinte é chamado depois que um evento é gerado em um elemento DOM, o valor this da função é o elemento DOM.

jQuery torna isso trivial para alterar com jQuery.proxy.

11 ArmanMcHitarian Apr 23 2013 at 19:57

Daniel, explicação incrível! Algumas palavras sobre esta e uma boa lista de thisponteiros de contexto de execução no caso de manipuladores de eventos.

Em duas palavras, thisem JavaScript aponta o objeto de quem (ou de cujo contexto de execução) a função atual foi executada e é sempre somente leitura, você não pode defini-la de qualquer maneira (tal tentativa terminará com 'Canhoto inválido lado na mensagem da atribuição.

Para manipuladores de eventos: os manipuladores de eventos embutidos, como <element onclick="foo">, sobrescrevem quaisquer outros manipuladores anexados antes e antes, portanto, tome cuidado e é melhor ficar longe da delegação de eventos embutidos. E obrigado a Zara Alaverdyan que me inspirou a esta lista de exemplos através de um debate dissidente :)

  • el.onclick = foo; // in the foo - obj
  • el.onclick = function () {this.style.color = '#fff';} // obj
  • el.onclick = function() {doSomething();} // In the doSomething - Window
  • el.addEventListener('click',foo,false) // in the foo - obj
  • el.attachEvent('onclick, function () { // this }') // window, all the compliance to IE :)
  • <button onclick="this.style.color = '#fff';"> // obj
  • <button onclick="foo"> // In the foo - window, but you can <button onclick="foo(this)">
11 zangw Nov 29 2015 at 13:01

Aqui é uma fonte boa de thisno JavaScript.

Aqui está o resumo:

  • global isso

    Em um navegador, no escopo global, thisestá o windowobjeto

    <script type="text/javascript">
      console.log(this === window); // true
      var foo = "bar";
      console.log(this.foo); // "bar"
      console.log(window.foo); // "bar"
    

    Ao nodeusar o repl, thisé o principal namespace. Você pode se referir a ele como global.

    >this
      { ArrayBuffer: [Function: ArrayBuffer],
        Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 },
        Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 },
        ...
    >global === this
     true
    

    Ao nodeexecutar a partir de um script, thisno escopo global começa como um objeto vazio. Não é o mesmo queglobal

    \\test.js
    console.log(this);  \\ {}
    console.log(this === global); \\ fasle
    
  • funcionar isso

Exceto no caso de manipuladores de eventos DOM ou quando um thisArgé fornecido (veja mais abaixo), tanto no nó quanto em um navegador usando thisuma função que não é chamada com newreferências ao escopo global ...

<script type="text/javascript">
    foo = "bar";

    function testThis() {
      this.foo = "foo";
    }

    console.log(this.foo); //logs "bar"
    testThis();
    console.log(this.foo); //logs "foo"
</script>

Se você usar use strict;, nesse caso thisseráundefined

<script type="text/javascript">
    foo = "bar";

    function testThis() {
      "use strict";
      this.foo = "foo";
    }

    console.log(this.foo); //logs "bar"
    testThis();  //Uncaught TypeError: Cannot set property 'foo' of undefined 
</script>

Se você chamar uma função com newo thisserá um novo contexto, não fará referência ao mundial this.

<script type="text/javascript">
    foo = "bar";

    function testThis() {
      this.foo = "foo";
    }

    console.log(this.foo); //logs "bar"
    new testThis();
    console.log(this.foo); //logs "bar"

    console.log(new testThis().foo); //logs "foo"
</script>
  • prototipar isso

As funções que você cria tornam-se objetos de função. Eles obtêm automaticamente uma prototypepropriedade especial , à qual você pode atribuir valores. Ao criar uma instância chamando sua função, newvocê obtém acesso aos valores atribuídos à prototypepropriedade. Você acessa esses valores usando this.

function Thing() {
  console.log(this.foo);
}

Thing.prototype.foo = "bar";

var thing = new Thing(); //logs "bar"
console.log(thing.foo);  //logs "bar"

Geralmente é um erro atribuir matrizes ou objetos no prototype. Se você quiser que as instâncias tenham seus próprios arrays, crie-os na função, não no protótipo.

function Thing() {
    this.things = [];
}

var thing1 = new Thing();
var thing2 = new Thing();
thing1.things.push("foo");
console.log(thing1.things); //logs ["foo"]
console.log(thing2.things); //logs []
  • objete isso

Você pode usar thisem qualquer função de um objeto para se referir a outras propriedades desse objeto. Isso não é o mesmo que uma instância criada com new.

var obj = {
    foo: "bar",
    logFoo: function () {
        console.log(this.foo);
    }
};

obj.logFoo(); //logs "bar"
  • Evento DOM este

Em um manipulador de eventos HTML DOM, thisé sempre uma referência ao elemento DOM ao qual o evento foi anexado

function Listener() {
    document.getElementById("foo").addEventListener("click",
       this.handleClick);
}
Listener.prototype.handleClick = function (event) {
    console.log(this); //logs "<div id="foo"></div>"
}

var listener = new Listener();
document.getElementById("foo").click();

A menos que você tenha bindo contexto

function Listener() {
    document.getElementById("foo").addEventListener("click", 
        this.handleClick.bind(this));
}
Listener.prototype.handleClick = function (event) {
    console.log(this); //logs Listener {handleClick: function}
}

var listener = new Listener();
document.getElementById("foo").click();
  • HTML isto

Dentro dos atributos HTML nos quais você pode colocar JavaScript, thisestá uma referência ao elemento.

<div id="foo" onclick="console.log(this);"></div>
<script type="text/javascript">
document.getElementById("foo").click(); //logs <div id="foo"...
</script>
  • avaliar isso

Você pode usar evalpara acessar this.

function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
    eval("console.log(this.foo)"); //logs "bar"
}

var thing = new Thing();
thing.logFoo();
  • com isso

Você pode usar withpara adicionar thisao escopo atual para ler e gravar valores thissem se referir thisexplicitamente.

function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
    with (this) {
        console.log(foo);
        foo = "foo";
    }
}

var thing = new Thing();
thing.logFoo(); // logs "bar"
console.log(thing.foo); // logs "foo"
  • jQuery isso

o jQuery, em muitos lugares, fará thisreferência a um elemento DOM.

<div class="foo bar1"></div>
<div class="foo bar2"></div>
<script type="text/javascript">
$(".foo").each(function () { console.log(this); //logs <div class="foo... }); $(".foo").on("click", function () {
    console.log(this); //logs <div class="foo...
});
$(".foo").each(function () {
    this.click();
});
</script>
9 ArupHore Jan 31 2017 at 15:29

Há muita confusão sobre como "esta" palavra-chave é interpretada em JavaScript. Esperançosamente, este artigo fará com que todos descansem de uma vez por todas. E muito mais. Por favor, leia todo o artigo com atenção. Esteja avisado de que este artigo é longo.

Independentemente do contexto em que é usado, "this" sempre faz referência ao "objeto atual" em Javascript. No entanto, o que é o "objeto atual" difere de acordo com o contexto . O contexto pode ser exatamente 1 dos 6 a seguir:

  1. Global (ou seja, fora de todas as funções)
  2. Chamada interna direta de "Função não vinculada" (ou seja, uma função que não foi vinculada chamando functionName.bind )
  3. Chamada interna indireta de "função não vinculada" por meio de functionName.call e functionName.apply
  4. Dentro da chamada de "Função vinculada" (ou seja, uma função que foi vinculada chamando functionName.bind )
  5. Enquanto Criação de Objetos por meio de "novo"
  6. Manipulador de eventos DOM Inline interno

O seguinte descreve cada um desses contextos, um por um:

  1. Global Context (i.e. Outside all functions):

    Outside all functions (i.e. in global context) the "current object" (and hence the value of "this") is always the "window" object for browsers.

  2. Inside Direct "Non Bound Function" Call:

    Inside a Direct "Non Bound Function" Call, the object that invoked the function call becomes the "current object" (and hence the value of "this"). If a function is called without a explicit current object, the current object is either the "window" object (For Non Strict Mode) or undefined (For Strict Mode) . Any function (or variable) defined in Global Context automatically becomes a property of the "window" object.For e.g Suppose function is defined in Global Context as

    function UserDefinedFunction(){
        alert(this)
        }
    

    it becomes the property of the window object, as if you have defined it as

    window.UserDefinedFunction=function(){
      alert(this)
    }  
    

    In "Non Strict Mode", Calling/Invoking this function directly through "UserDefinedFunction()" will automatically call/invoke it as "window.UserDefinedFunction()" making "window" as the "current object" (and hence the value of "this") within "UserDefinedFunction".Invoking this function in "Non Strict Mode" will result in the following

    UserDefinedFunction() // displays [object Window]  as it automatically gets invoked as window.UserDefinedFunction()
    

    In "Strict Mode", Calling/Invoking the function directly through "UserDefinedFunction()" will "NOT" automatically call/invoke it as "window.UserDefinedFunction()".Hence the "current object" (and the value of "this") within "UserDefinedFunction" shall be undefined. Invoking this function in "Strict Mode" will result in the following

    UserDefinedFunction() // displays undefined
    

    However, invoking it explicitly using window object shall result in the following

    window.UserDefinedFunction() // "always displays [object Window]   irrespective of mode."
    

    Let us look at another example. Please look at the following code

     function UserDefinedFunction()
        {
            alert(this.a + ","  + this.b + ","  + this.c  + ","  + this.d)
        }
    
    var o1={
                a:1,
                b:2,
                f:UserDefinedFunction
          }
    var o2={
                c:3,
                d:4,
                f:UserDefinedFunction
           }
    
    o1.f() // Shall display 1,2,undefined,undefined
    o2.f() // Shall display undefined,undefined,3,4
    

    In the above example we see that when "UserDefinedFunction" was invoked through o1, "this" takes value of o1 and the value of its properties "a" and "b" get displayed. The value of "c" and "d" were shown as undefined as o1 does not define these properties

    Similarly when "UserDefinedFunction" was invoked through o2, "this" takes value of o2 and the value of its properties "c" and "d" get displayed.The value of "a" and "b" were shown as undefined as o2 does not define these properties.

  3. Inside Indirect "Non Bound Function" Call through functionName.call and functionName.apply:

    When a "Non Bound Function" is called through functionName.call or functionName.apply, the "current object" (and hence the value of "this") is set to the value of "this" parameter (first parameter) passed to call/apply. The following code demonstrates the same.

    function UserDefinedFunction()
    {
        alert(this.a + ","  + this.b + ","  + this.c  + ","  + this.d)
    }
    var o1={
                a:1,
                b:2,
                f:UserDefinedFunction
           }
    var o2={
                c:3,
                d:4,
                f:UserDefinedFunction
           }
    
    UserDefinedFunction.call(o1) // Shall display 1,2,undefined,undefined
    UserDefinedFunction.apply(o1) // Shall display 1,2,undefined,undefined
    
    UserDefinedFunction.call(o2) // Shall display undefined,undefined,3,4
    UserDefinedFunction.apply(o2) // Shall display undefined,undefined,3,4
    
    o1.f.call(o2) // Shall display undefined,undefined,3,4
    o1.f.apply(o2) // Shall display undefined,undefined,3,4
    
    o2.f.call(o1) // Shall display 1,2,undefined,undefined
    o2.f.apply(o1) // Shall display 1,2,undefined,undefined
    

    The above code clearly shows that the "this" value for any "NON Bound Function" can be altered through call/apply. Also,if the "this" parameter is not explicitly passed to call/apply, "current object" (and hence the value of "this") is set to "window" in Non strict mode and "undefined" in strict mode.

  4. Inside "Bound Function" Call (i.e. a function that has been bound by calling functionName.bind):

    A bound function is a function whose "this" value has been fixed. The following code demonstrated how "this" works in case of bound function

    function UserDefinedFunction()
    {
        alert(this.a + ","  + this.b + ","  + this.c  + ","  + this.d)
    }
    var o1={
              a:1,
              b:2,
              f:UserDefinedFunction,
              bf:null
           }
    var o2={
               c:3,
               d:4,
               f:UserDefinedFunction,
               bf:null
            }
    
    var bound1=UserDefinedFunction.bind(o1); // permanantly fixes "this" value of function "bound1" to Object o1
    bound1() // Shall display 1,2,undefined,undefined
    
    var bound2=UserDefinedFunction.bind(o2); // permanantly fixes "this" value of function "bound2" to Object o2
    bound2() // Shall display undefined,undefined,3,4
    
    var bound3=o1.f.bind(o2); // permanantly fixes "this" value of function "bound3" to Object o2
    bound3() // Shall display undefined,undefined,3,4
    
    var bound4=o2.f.bind(o1); // permanantly fixes "this" value of function "bound4" to Object o1
    bound4() // Shall display 1,2,undefined,undefined
    
    o1.bf=UserDefinedFunction.bind(o2) // permanantly fixes "this" value of function "o1.bf" to Object o2
    o1.bf() // Shall display undefined,undefined,3,4
    
    o2.bf=UserDefinedFunction.bind(o1) // permanantly fixes "this" value of function "o2.bf" to Object o1
    o2.bf() // Shall display 1,2,undefined,undefined
    
    bound1.call(o2) // Shall still display 1,2,undefined,undefined. "call" cannot alter the value of "this" for bound function
    
    bound1.apply(o2) // Shall still display 1,2,undefined,undefined. "apply" cannot alter the value of "this" for bound function
    
    o2.bf.call(o2) // Shall still display 1,2,undefined,undefined. "call" cannot alter the value of "this" for bound function
    o2.bf.apply(o2) // Shall still display 1,2,undefined,undefined."apply" cannot alter the value of "this" for bound function
    

    As given in the code above, "this" value for any "Bound Function" CANNOT be altered through call/apply. Also, if the "this" parameter is not explicitly passed to bind, "current object" (and hence the value of "this" ) is set to "window" in Non strict mode and "undefined" in strict mode. One more thing. Binding an already bound function does not change the value of "this". It remains set as the value set by first bind function.

  5. While Object Creation through "new":

    Inside a constructor function, the "current object" (and hence the value of "this") references the object that is currently being created through "new" irrespective of the bind status of the function. However if the constructor is a bound function it shall get called with predefined set of arguments as set for the bound function.

  6. Inside Inline DOM event handler:

    Please look at the following HTML Snippet

    <button onclick='this.style.color=white'>Hello World</button>
    <div style='width:100px;height:100px;' onclick='OnDivClick(event,this)'>Hello World</div>
    

    The "this" in above examples refer to "button" element and the "div" element respectively.

    In the first example, the font color of the button shall be set to white when it is clicked.

    In the second example when the "div" element is clicked it shall call the OnDivClick function with its second parameter referencing the clicked div element. However the value of "this" within OnDivClick SHALL NOT reference the clicked div element. It shall be set as the "window object" or "undefined" in Non strict and Strict Modes respectively (if OnDivClick is an unbound function) or set to a predefined Bound value (if OnDivClick is a bound function)

The following summarizes the entire article

  1. In Global Context "this" always refers to the "window" object

  2. Whenever a function is invoked, it is invoked in context of an object ("current object"). If the current object is not explicitly provided, the current object is the "window object" in NON Strict Mode and "undefined" in Strict Mode by default.

  3. The value of "this" within a Non Bound function is the reference to object in context of which the function is invoked ("current object")

  4. The value of "this" within a Non Bound function can be overriden by call and apply methods of the function.

  5. The value of "this" is fixed for a Bound function and cannot be overriden by call and apply methods of the function.

  6. Binding and already bound function does not change the value of "this". It remains set as the value set by first bind function.

  7. The value of "this" within a constructor is the object that is being created and initialized

  8. The value of "this" within an inline DOM event handler is reference to the element for which the event handler is given.

9 DmitriPavlutin Nov 08 2016 at 19:17

Probably the most detailed and comprehensive article on this is the following:

Gentle explanation of 'this' keyword in JavaScript

The idea behind this is to understand that the function invocation types have the significant importance on setting this value.


When having troubles identifying this, do not ask yourself:

Where is this taken from?

but do ask yourself:

How is the function invoked?

For an arrow function (special case of context transparency) ask yourself:

What value has this where the arrow function is defined?

This mindset is correct when dealing with this and will save you from headache.

7 JamesDrinkard Jul 13 2016 at 02:03

This is the best explanation I've seen: Understand JavaScripts this with Clarity

The this reference ALWAYS refers to (and holds the value of) an object—a singular object—and it is usually used inside a function or a method, although it can be used outside a function in the global scope. Note that when we use strict mode, this holds the value of undefined in global functions and in anonymous functions that are not bound to any object.

There are Four Scenarios where this can be confusing:

  1. When we pass a method (that uses this) as an argument to be used as a callback function.
  2. When we use an inner function (a closure). It is important to take note that closures cannot access the outer function’s this variable by using the this keyword because the this variable is accessible only by the function itself, not by inner functions.
  3. When a method which relies on this is assigned to a variable across contexts, in which case this references another object than originally intended.
  4. When using this along with the bind, apply, and call methods.

He gives code examples, explanations, and solutions, which I thought was very helpful.

6 Nipuna Aug 09 2014 at 16:22

this is one of the misunderstood concept in JavaScript because it behaves little differently from place to place. Simply, this refers to the "owner" of the function we are currently executing.

this helps to get the current object (a.k.a. execution context) we work with. If you understand in which object the current function is getting executed, you can understand easily what current this is

var val = "window.val"

var obj = {
    val: "obj.val",
    innerMethod: function () {
        var val = "obj.val.inner",
            func = function () {
                var self = this;
                return self.val;
            };

        return func;
    },
    outerMethod: function(){
        return this.val;
    }
};

//This actually gets executed inside window object 
console.log(obj.innerMethod()()); //returns window.val

//Breakdown in to 2 lines explains this in detail
var _inn = obj.innerMethod();
console.log(_inn()); //returns window.val

console.log(obj.outerMethod()); //returns obj.val

Above we create 3 variables with same name 'val'. One in global context, one inside obj and the other inside innerMethod of obj. JavaScript resolves identifiers within a particular context by going up the scope chain from local go global.


Few places where this can be differentiated

Calling a method of a object

var status = 1;
var helper = {
    status : 2,
    getStatus: function () {
        return this.status;
    }
};

var theStatus1 = helper.getStatus(); //line1
console.log(theStatus1); //2

var theStatus2 = helper.getStatus;
console.log(theStatus2()); //1

When line1 is executed, JavaScript establishes an execution context (EC) for the function call, setting this to the object referenced by whatever came before the last ".". so in the last line you can understand that a() was executed in the global context which is the window.

With Constructor

this can be used to refer to the object being created

function Person(name){
    this.personName = name;
    this.sayHello = function(){
        return "Hello " + this.personName;
    }
}

var person1 = new Person('Scott');
console.log(person1.sayHello()); //Hello Scott

var person2 = new Person('Hugh');
var sayHelloP2 = person2.sayHello;
console.log(sayHelloP2()); //Hello undefined

When new Person() is executed, a completely new object is created. Person is called and its this is set to reference that new object.

Function call

function testFunc() {
    this.name = "Name";
    this.myCustomAttribute = "Custom Attribute";
    return this;
}

var whatIsThis = testFunc();
console.log(whatIsThis); //window

var whatIsThis2 = new testFunc();
console.log(whatIsThis2);  //testFunc() / object

console.log(window.myCustomAttribute); //Custom Attribute 

If we miss new keyword, whatIsThis referes to the most global context it can find(window)

With event handlers

If the event handler is inline, this refers to global object

<script type="application/javascript">
    function click_handler() {
        alert(this); // alerts the window object
    }
</script>

<button id='thebutton' onclick='click_handler()'>Click me!</button>

When adding event handler through JavaScript, this refers to DOM element that generated the event.


  • You can also manipulate the context using .apply() .call() and .bind()
  • JQuery proxy is another way you can use to make sure this in a function will be the value you desire. (Check Understanding $.proxy(), jQuery.proxy() usage)
  • What does var that = this means in JavaScript
6 mrmaclean89 Sep 17 2017 at 05:11

In pseudoclassical terms, the way many lectures teach the 'this' keyword is as an object instantiated by a class or object constructor. Each time a new object is constructed from a class, imagine that under the hood a local instance of a 'this' object is created and returned. I remember it taught like this:

function Car(make, model, year) {
var this = {}; // under the hood, so to speak
this.make = make;
this.model = model;
this.year = year;
return this; // under the hood
}

var mycar = new Car('Eagle', 'Talon TSi', 1993);
// ========= under the hood
var this = {};
this.make = 'Eagle';
this.model = 'Talon TSi';
this.year = 1993;
return this;
5 Trombe Jul 03 2017 at 17:07

The value of "this" depends on the "context" in which the function is executed. The context can be any object or the global object, i.e., window.

So the Semantic of "this" is different from the traditional OOP languages. And it causes problems: 1. when a function is passed to another variable (most likely, a callback); and 2. when a closure is invoked from a member method of a class.

In both cases, this is set to window.

4 SimonGroenewolt Jun 27 2010 at 20:15

Whould this help? (Most confusion of 'this' in javascript is coming from the fact that it generally is not linked to your object, but to the current executing scope -- that might not be exactly how it works but is always feels like that to me -- see the article for a complete explanation)

3 unclexo Jul 25 2018 at 14:04

A little bit info about this keyword

Let's log this keyword to the console in global scope without any more code but

console.log(this)

In Client/Browser this keyword is a global object which is window

console.log(this === window) // true

and

In Server/Node/Javascript runtime this keyword is also a global object which is module.exports

console.log(this === module.exports) // true
console.log(this === exports) // true

Keep in mind exports is just a reference to module.exports

1 PRADEEPSINGHChundawat Apr 06 2016 at 14:15

this use for Scope just like this

  <script type="text/javascript" language="javascript">
$('#tbleName tbody tr').each(function{ var txt=''; txt += $(this).find("td").eq(0).text();
\\same as above but synatx different
var txt1='';
 txt1+=$('#tbleName tbody tr').eq(0).text();
alert(txt1)
});
</script>

value of txt1 and txt is same in Above example $(this)=$('#tbleName tbody tr') is Same

1 gman Jan 29 2019 at 01:37

I have a different take on this from the other answers that I hope is helpful.

One way to look at JavaScript is to see that there are only 1 way to call a function1. It is

functionObject.call(objectForThis, arg0, arg1, arg2, ...);

There is always some value supplied for objectForThis.

Everything else is syntactic sugar for functionObject.call

So, everything else can be described by how it translates into functionObject.call.

If you just call a function then this is the "global object" which in the browser is the window

function foo() {
  console.log(this);
}

foo();  // this is the window object

In other words,

foo();

was effectively translated into

foo.call(window);

Note that if you use strict mode then this will be undefined

'use strict';

function foo() {
  console.log(this);
}

foo();  // this is the window object

which means

In other words,

foo();

was effectively translated into

foo.call(undefined);

In JavaScript there are operators like + and - and *. There is also the dot operator which is .

The . operator when used with a function on the right and an object on the left effectively means "pass object as this to function.

Example

const bar = {
  name: 'bar',
  foo() { 
    console.log(this); 
  },
};

bar.foo();  // this is bar

In other words bar.foo() translates into const temp = bar.foo; temp.call(bar);

Note that it doesn't matter how the function was created (mostly...). All of these will produce the same results

const bar = {
  name: 'bar',
  fn1() { console.log(this); },
  fn2: function() { console.log(this); },
  fn3: otherFunction,
};

function otherFunction() { console.log(this) };

bar.fn1();  // this is bar
bar.fn2();  // this is bar
bar.fn3();  // this is bar

Again these all are just syntactic sugar for

{ const temp = bar.fn1; temp.call(bar); }
{ const temp = bar.fn2; temp.call(bar); }
{ const temp = bar.fn3; temp.call(bar); }

One other wrinkle is the prototype chain. When you use a.b JavaScript first looks on the object referenced directly by a for the property b. If b is not found on the object then JavaScript will look in the object's prototype to find b.

There are various ways to define an object's prototype, the most common in 2019 is the class keyword. For the purposes of this though it doesn't matter. What matters is that as it looks in object a for property b if it finds property b on the object or in it's prototype chain if b ends up being a function then the same rules as above apply. The function b references will be called using the call method and passing a as objectForThis as shown a the top of this answer.

Now. Let's imagine we make a function that explicitly sets this before calling another function and then call it with the . (dot) operator

function foo() {
  console.log(this);
}

function bar() {
  const objectForThis = {name: 'moo'}
  foo.call(objectForThis);  // explicitly passing objectForThis
}

const obj = {
  bar,
};

obj.bar();  

Following the translation to use call, obj.bar() becomes const temp = obj.bar; temp.call(obj);. When we enter the bar function we call foo but we explicitly passed in another object for objectForThis so when we arrive at foo this is that inner object.

This is what both bind and => functions effectively do. They are more syntactic sugar. They effectively build a new invisible function exactly like bar above that explicitly sets this before it calls whatever function is specified. In the case of bind this is set to whatever you pass to bind.

function foo() {
  console.log(this);
}

const bar = foo.bind({name: 'moo'});

// bind created a new invisible function that calls foo with the bound object.

bar();  

// the objectForThis we are passing to bar here is ignored because
// the invisible function that bind created will call foo with with
// the object we bound above

bar.call({name: 'other'});

Note that if functionObject.bind did not exist we could make our own like this

function bind(fn, objectForThis) {
  return function(...args) {
    return fn.call(objectForthis, ...args);
  };
}

and then we could call it like this

function foo() {
  console.log(this);
}

const bar = bind(foo, {name:'abc'});

Arrow functions, the => operator are syntactic sugar for bind

const a = () => {console.log(this)};

is the same as

const tempFn = function() {console.log(this)}; 
const a = tempFn.bind(this);

Just like bind, a new invisible function is created that calls the given function with a bound value for objectForThis but unlike bind the object to be bound is implicit. It's whatever this happens to be when the => operator is used.

So, just like the rules above

const a = () => { console.log(this); }  // this is the global object
'use strict';
const a = () => { console.log(this); }  // this is undefined
function foo() {
  return () => { console.log(this); }
}

const obj = {
  foo,
};
const b = obj.foo();
b();

obj.foo() translates to const temp = obj.foo; temp.call(obj); which means the arrow operator inside foo will bind obj to a new invisible function and return that new invisible function which is assigned to b. b() will work as it always has as b.call(window) or b.call(undefined) calling the new invisible function that foo created. That invisible function ignores the this passed into it and passes obj as objectForThis` to the arrow function.

The code above translates to

function foo() {
  function tempFn() {
    console.log(this);
  }
  return tempFn.bind(this);
}

const obj = {
  foo,
};
const b = obj.foo();
b.call(window or undefined if strict mode);

1apply is another function similar to call

functionName.apply(objectForThis, arrayOfArgs);

But as of ES6 conceptually you can even translate that into

functionName.call(objectForThis, ...arrayOfArgs);
WillemvanderVeen Aug 22 2018 at 00:12

Summary this Javascript:

  • The value of this is determined by how the function is invoked not, where it was created!
  • Usually the value of this is determined by the Object which is left of the dot. (window in global space)
  • In event listeners the value of this refers to the DOM element on which the event was called.
  • When in function is called with the new keyword the value of this refers to the newly created object
  • You can manipulate the value of this with the functions: call, apply, bind

Example:

let object = {
  prop1: function () {console.log(this);}
}

object.prop1();   // object is left of the dot, thus this is object

const myFunction = object.prop1 // We store the function in the variable myFunction

myFunction(); // Here we are in the global space
              // myFunction is a property on the global object
              // Therefore it logs the window object
              
             

Example event listeners:

document.querySelector('.foo').addEventListener('click', function () {
  console.log(this);   // This refers to the DOM element the eventListener was invoked from
})


document.querySelector('.foo').addEventListener('click', () => {
  console.log(this);  // Tip, es6 arrow function don't have their own binding to the this v
})                    // Therefore this will log the global object
.foo:hover {
  color: red;
  cursor: pointer;
}
<div class="foo">click me</div>

Example constructor:

function Person (name) {
  this.name = name;
}

const me = new Person('Willem');
// When using the new keyword the this in the constructor function will refer to the newly created object

console.log(me.name); 
// Therefore, the name property was placed on the object created with new keyword.

Lord May 20 2020 at 16:43

To understand "this" properly one must understand the context and scope and difference between them.

Scope: In javascript scope is related to the visibility of the variables, scope achieves through the use of the function. (Read more about scope)

Context: Context is related to objects. It refers to the object to which a function belongs. When you use the JavaScript “this” keyword, it refers to the object to which function belongs. For example, inside of a function, when you say: “this.accoutNumber”, you are referring to the property “accoutNumber”, that belongs to the object to which that function belongs.

If the object “myObj” has a method called “getMyName”, when the JavaScript keyword “this” is used inside of “getMyName”, it refers to “myObj”. If the function “getMyName” were executed in the global scope, then “this” refers to the window object (except in strict mode).

Now let's see some example:

    <script>
        console.log('What is this: '+this);
        console.log(this);
    </script>

Runnig abobve code in browser output will:

According to the output you are inside of the context of the window object, it is also visible that window prototype refers to the Object.

Now let's try inside of a function:

    <script>
        function myFunc(){
            console.log('What is this: '+this);
            console.log(this);
        }
        myFunc();
    </script>

Output:

The output is the same because we logged 'this' variable in the global scope and we logged it in functional scope, we didn't change the context. In both case context was same, related to widow object.

Now let's create our own object. In javascript, you can create an object in many ways.

 <script>
        var firstName = "Nora";
        var lastName = "Zaman";
        var myObj = {
            firstName:"Lord",
            lastName:'Baron',
            printNameGetContext:function(){
                console.log(firstName + " "+lastName);
                console.log(this.firstName +" "+this.lastName);
                return this;
            }
        }

      var context = myObj.printNameGetContext();
      console.log(context);
    </script>

Output:

So from the above example, we found that 'this' keyword is referring to a new context that is related to myObj, and myObject also has prototype chain to Object.

Let's go throw another example:

<body>
    <button class="btn">Click Me</button>
    <script>
        function printMe(){
            //Terminal2: this function declared inside window context so this function belongs to the window object.
            console.log(this);
        }
        document.querySelector('.btn').addEventListener('click', function(){
            //Terminal1: button context, this callback function belongs to DOM element 
            console.log(this);
            printMe();
        })
    </script>
</body>

output: Make sense right? (read comments)

If you having trouble to understand the above example let's try with our own callback;

<script>
        var myObj = {
            firstName:"Lord",
            lastName:'Baron',
            printName:function(callback1, callback2){
                //Attaching callback1 with this myObj context
                this.callback1 = callback1;
                this.callback1(this.firstName +" "+this.lastName)
                //We did not attached callback2 with myObj so, it's reamin with window context by default
                callback2();
                /*
                 //test bellow codes
                 this.callback2 = callback2;
                 this.callback2();
                */
            }
        }
        var callback2 = function (){
            console.log(this);
        }
        myObj.printName(function(data){
            console.log(data);
            console.log(this);
        }, callback2);
    </script>

output:

Now let's Understand Scope, Self, IIFE and THIS how behaves

       var color = 'red'; // property of window
       var obj = {
           color:'blue', // property of window
           printColor: function(){ // property of obj, attached with obj
               var self = this;
               console.log('In printColor -- this.color: '+this.color);
               console.log('In printColor -- self.color: '+self.color);
               (function(){ // decleard inside of printColor but not property of object, it will executed on window context.
                    console.log(this)
                    console.log('In IIFE -- this.color: '+this.color);
                    console.log('In IIFE -- self.color: '+self.color); 
               })();

               function nestedFunc(){// decleard inside of printColor but not property of object, it will executed on window context.
                    console.log('nested fun -- this.color: '+this.color);
                    console.log('nested fun -- self.color: '+self.color);
               }

               nestedFunc(); // executed on window context
               return nestedFunc;
           }
       };

       obj.printColor()(); // returned function executed on window context
   </script> 

Output is pretty awesome right?