Como a palavra-chave "this" funciona?

1309

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

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

Como thisfunciona e quando deve ser usado?

Maxim Gershkovich
fonte
6
Encontrei isso quando pesquisei "this" no quirksmode.org/js/this.html #
Wai Wong
2
Peter Michaux defende contra o uso de this peter.michaux.ca/articles/javascript-widgets-without-this
Marcel Korpel
1
A visão geral do MDN não é tão ruim ... developer.mozilla.org/pt-BR/docs/JavaScript/Reference/Operators/…
dat
2
Uma explicação interessante da thispalavra-chave: rainsoft.io/gentle-explanation-of-this-in-javascript
Dmitri Pavlutin

Respostas:

1350

Eu recomendo ler o artigo de Mike West Scope em JavaScript ( espelho ) primeiro. É uma introdução excelente e amigável aos conceitos thise cadeias de escopo em JavaScript.

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

§11.1.1 A thispalavra-chave

A thispalavra-chave é avaliada como o valor de ThisBinding do atual contexto de execução

ThisBinding é algo que o intérprete JavaScript mantém ao avaliar o código JavaScript, como um registro especial da CPU que mantém uma referência a um objeto. O intérprete atualiza o ThisBinding sempre que estabelecer um contexto de execução em um dos três casos diferentes:

1. Contexto inicial de execução global

Este é o caso do código JavaScript que é avaliado no nível superior, por exemplo, quando diretamente dentro de um <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 inicial de execução global, ThisBinding é definido como o objeto global window( §10.4.1.1 ).

Introduzir código de avaliação

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

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

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

Introduzir código de função

Isso ocorre ao chamar uma função. Se uma função é chamada em um objeto, como em obj.myMethod()ou equivalente obj["myMethod"](), ThisBinding é definido como 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 internas do ECMAScript 5 que permitem que ThisBinding seja especificado na lista de argumentos. Essas funções especiais usam o chamado thisArgque se torna o 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 para 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 em que ThisBinding está definido como thisArgse for fornecido; caso contrário, para o objeto global.

Essas são as regras para JavaScript simples. Ao começar a usar bibliotecas JavaScript (por exemplo, jQuery), você pode achar que determinadas funções da biblioteca manipulam o valor de this. Os desenvolvedores dessas bibliotecas JavaScript fazem isso porque tendem a suportar os casos de uso mais comuns, e os usuários da biblioteca geralmente acham esse comportamento mais conveniente. Ao transmitir funções de retorno de chamada referentes thisa funções de biblioteca, você deve consultar a documentação para obter garantias sobre qual é o valor 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 incorporadas que aceitam a thisArg. Você também pode escrever sua própria função usando 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, em seguida, 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 intérprete 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 da seta versus declaração / expressões da função: Eles são equivalentes / intercambiáveis? Para maiores informações. Mas em suma:

As funções de seta não têm seus próprios this.... vínculos. Em vez disso, esses identificadores são resolvidos no escopo lexical como qualquer outra variável. Isso significa que, dentro de uma função de seta, this... se referem aos valores thisno ambiente em que a função de seta está 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? Por quê?

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

    if (true) {
        // What is `this` here?
    }
  2. Qual é o valor da thislinha marcada quando obj.staticFunction()é executado? Por quê?

    obj - Ao chamar uma função em um objeto, ThisBinding é definido como 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);
      

  3. Qual é o valor de thisna linha marcada? Por quê?

    window

    Neste exemplo, o intérprete JavaScript insere o código de função, mas porque myFun/ obj.myMethodnão é chamado em um objeto, ThisBinding está definido como window.

    Isso é diferente do Python, no qual o acesso a 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);
      

  4. Qual é o valor de thisna linha marcada? Por quê?

    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 está definido como windowpara a chamada.

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

    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);
      

Daniel Trebbien
fonte
6
@ Ali: São referências a seções da edição 5.1 do ECMAScript Standard, ECMA-262 . Eu os forneço para que você possa ler o Padrão para obter detalhes técnicos, se desejar.
Daniel Trebbien
1
Eu acho que @supertonsky está certo sobre # 2 - se myFun () for chamado do escopo global, e não como um método no objeto, "this" será o objeto global, portanto a formulação da pergunta é importante. btw - Eu realmente gosto da idéia de usar o mouseover para obter a resposta para algo assim.
user655489
2
Mas, jsfiddle.net/H4LYm/2 mostra que o setTimeoutexemplo tem um thisde window(global).
Kevin Meredith
2
vindo do Python se poderia imaginar os níveis de frustração que tive quando esbarrou na 3ª exemplo .. SMH
Marius Mucenicu
1
Essa resposta provavelmente deve ser atualizada para refletir a realidade do ES2020, mesmo que as mudanças sejam apenas terminológicas.
Ben Aston
156

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

1. Quando usado no contexto global

Quando você usa thisno contexto global, ele é 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 é realmente transformada em 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 de objeto

Quando você usa a 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. É importante ressaltar que, se você aninhar o objeto dentro de outro objeto, thisserá 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 uma função explicitamente ao objeto como método, ela ainda segue as regras acima, que thisainda apontam 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 chamar a função sem contexto

Quando você usa a thisfunção interna que é chamada sem nenhum contexto (ou seja, não está em nenhum objeto), ela é vinculada ao objeto global ( windowno navegador) (mesmo que a função esteja 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 

Tentando tudo com funções

Também podemos tentar os pontos acima com funções. 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, talvez seja necessário primeiro criar sua instância usando newoperator.
  • Também em uma abordagem literal de objeto, podemos adicionar explicitamente membros ao objeto já definido usando o operador de ponto. Isso é adicionado apenas à instância específica. No entanto, adicionei variável ao protótipo da função para que ele seja refletido em todas as instâncias da função.

Abaixo, tentei todas as coisas que fizemos com o Object e thisacima, mas primeiro criando a função em vez de escrever diretamente um objeto.

/********************************************************************* 
  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 construtora .

Quando a função é usada como construtor (ou seja, é chamada com newpalavra - chave), o thiscorpo interno da função 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ótipos

Se o método estiver 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. Funções internas de chamada (), apply () e bind ()

  • Todos esses métodos estão definidos em Function.prototype.
  • Esses métodos permitem escrever uma função uma vez e invocá-la em um contexto diferente. Em outras palavras, eles permitem especificar o valor thisque será usado enquanto a função estiver sendo executada. Eles também levam todos os parâmetros a serem passados ​​para a função original quando ela é chamada.
  • fun.apply(obj1 [, argsArray])Define obj1como o valor de thisinside fun()e chama fun()elementos passantes 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 thisdiversão interna vinculada a obj1e parâmetros de funvinculada aos 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 objeto de matriz, 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 vinculada ao thisvalor especificado e aos argumentos. Podemos capturar a referência a essa 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 uma função diretamente aos manipuladores de eventos de um elemento, o uso da thisfunção de manipulação de eventos diretamente interna refere-se ao elemento correspondente. Essa atribuição direta de função pode ser feita usando o addeventListenermétodo ou através dos métodos tradicionais de registro de eventos, como onclick.
  • Da mesma forma, quando você usa thisdiretamente dentro da propriedade de evento (like <button onclick="...this..." >) do elemento, ela se refere ao elemento
  • No entanto, o uso thisindireto de outra função chamada dentro da função de manipulação de eventos ou propriedade do evento é resolvido para o objeto global window.
  • O mesmo comportamento acima é alcançado 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-o no contexto global).

Eu recomendo tentar melhor isso 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, thiscomportará-se como variáveis ​​comuns: será herdada de seu escopo lexical. A função this, onde a função de seta é definida, será a função de seta this.

Portanto, 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 
Mahesha999
fonte
"Quando você usa isso dentro de uma função definida no contexto global, isso ainda está vinculado ao objeto global, pois a função é realmente transformada em um método de contexto global". está incorreto. isso é definido pelo modo como uma função é chamada ou pelo bind , não pelo local em que é definida. Chamar qualquer função sem uma referência de base ("contexto") padronizará isso para o objeto global ou permanecerá indefinido no modo estrito.
RobG
@RobG hmm pode ser, mas achei isso no MDN : Nesse caso, o valor de thisnão é definido pela chamada. Como o código não está no modo estrito, o valor de thisdeve sempre ser um objeto, por padrão, para o objeto global. E, de fato, foi por isso que pensei que poderíamos fazer chamadas diretamente window.f1(), de modo que o meio f1()já está anexado ao windowobjeto, antes da invocação. Estou entendendo errado?
Mahesha999
Eu estava comentando (talvez não claramente) sobre como você vincula a configuração disso com "a função é realmente transformada em um método do contexto global", como se fosse meio que chamada window.fn, o que não é. o padrão é o objeto global porque nenhuma referência base foi usada na chamada, não por onde a função está definida (portanto, isso ainda é definido pelo modo como a função foi chamada). Se você chamá-lo explicitamente usando window.fn, está configurando isso para janela . Mesmo resultado, uma maneira diferente de fazer isso. :-)
RobG
"acima eu coloquei a palavra imediatamente ..." não, você não fez. Você pode revisar isso para que o erro seja corrigido? Parece semântico para a resposta e, portanto, não posso continuar lendo até que o erro seja corrigido por medo de aprender algo incorreto.
precisa saber é o seguinte
@TylerH fazer Ctrl + F desta página em seu navegador para encontrar string "imediata" (incluindo as aspas) Eu acho que é lá se estou entendendo u errado
Mahesha999
64

Javascript this

Chamada 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 pedaço de código em um ambiente como o node.js, thisconsulte a variável global no 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 se referirá mais à variável global em nenhum dos ambientes. Isso é feito para evitar confusões no modo estrito. thisnesse caso, apenas registraria undefined, porque é isso que é, não está definido.

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

Chamando uma função em um objeto

Existem diferentes maneiras de fazer isso. Se você tem chamado métodos nativos em Javascript como forEache slice, você já deve saber que a thisvariável, nesse caso, refere-se ao Objectem que você chamou essa função (Note-se que em javascript, quase tudo é um Object, incluindo Arrays e Functions). Pegue o seguinte código, 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 a Function, a propriedade é chamada de método. Este método, quando chamado, sempre terá sua thisvariável definida como a Objectqual está associada. Isso vale 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 disso Objecttem seu construtor definido como Person. Além disso, observe que typeof awalretornaria Objectapenas.
  3. A este novo Objectseria atribuído o 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, inclusive awal.
  4. A função em Personsi agora é invocada; thissendo uma referência ao objeto recém-construído awal.

Bem direto, não é?

Observe que a especificação oficial do ECMAScript em nenhum lugar afirma que esses tipos de funções são reais constructor. São apenas funções normais e newpodem ser usadas em qualquer função. É que nós os usamos como tal e, portanto, os chamamos apenas como tal.

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

Então sim, como functions também são Objects(e de fato variáveis ​​de primeira classe em Javascript), até as funções têm métodos que são ... bem, elas próprias.

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 da thisfunçã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, pega o primeiro parâmetro e define thisa função foocomo referência thisArg. Todos os outros parâmetros passados callsão passados ​​para a função foocomo argumentos.
Portanto, o código acima fará logon {myObj: "is cool"}, [1, 2, 3]no console. Maneira bastante agradável de alterar o valor de thisem qualquer função.

applyé quase o mesmo que callaceitar que são necessários apenas dois parâmetros: thisArge uma matriz que contém os argumentos a serem passados ​​para a função. Portanto, a callchamada acima pode ser traduzida para apply:

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

Observe que calle applypode substituir o valor da thischamada de método definido por ponto que discutimos no segundo marcador. 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 chamarão a função. bind, por outro lado, retorna uma nova função com thisArge argumentspré-configurada. 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 maneira diferente. Like calle apply, bindtambém substituem o valor de thisset pela chamada do método dot.

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

Coisas extras, copie isso

Às vezes, você não gosta do fato de que thismuda com o escopo, especialmente o escopo aninhado. Veja o 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 do thisescopo original. Então nós 'copiado' thisa thate usou a copiar em vez de this. Inteligente, não é?

Índice:

  1. O que é mantido thispor padrão?
  2. E se chamarmos a função como um método com a notação Objeto-ponto?
  3. E se usarmos a newpalavra - chave?
  4. Como podemos manipular thiscom calle apply?
  5. Usando bind.
  6. Copiando thispara resolver problemas de escopo aninhado.
user3459110
fonte
47

"this" tem tudo a ver com escopo. Toda função tem seu próprio escopo e, como tudo em JS é um objeto, mesmo uma função pode armazenar alguns valores em si mesma usando "this". OOP 101 ensina que "isso" é aplicável apenas a instâncias de um objeto. Portanto, sempre que uma função é executada, uma nova "instância" dessa função tem um novo significado de "this".

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

(função (valor) {
    this.value = value;
    $ ('. alguns elementos'). each (function (elt) {
        elt.innerHTML = this.value; // ah oh !! possivelmente indefinido
    });
}) (2);

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

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

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

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

arunjitsingh
fonte
6
"tudo em JS é um objeto" não é verdade, JavaScript também tem valores primitivos, ver bclary.com/2004/11/07/#a-4.3.2
Marcel Korpel
6
Os valores primitivos parecem ter alguns métodos, como String # substring (), Number # toString (), etc. Então, talvez não com a mesma nomenclatura desse artigo, eles realmente se comportam como se fossem objetos (eles são todos prototipados, ou seja, a string # substring () é realmente: String.prototype.substring = function () {...}). Por favor me corrija se eu estiver errado.
Arunjitsingh
12
A thispalavra-chave não tem nada a ver com escopo. Além disso, também tem um significado em funções que não são propriedades de objetos.
Bergi
1
@ arunjitsingh - existem duas escolas de pensamento sobre isso. Gosto do que diz " tudo é um objeto, mas alguns podem ser representados por primitivos por conveniência ". ;-)
RobG
9
thisnão é tudo sobre escopo. É tudo sobre o contexto de execução, que não é a mesma coisa que escopo. O JavaScript tem escopo lexical (o escopo é determinado pela localização do código), mas thisé determinado pela maneira como a função que o contém é invocada - e não onde essa função está.
Scott Marcus
16

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

Como é thisdeterminado o valor ?

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 chame a função em que 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 (e tem o valor de) ao windowobjeto global .

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

A thispalavra-chave é mais incompreendida quando: 1) emprestamos um método que usa this, 2) atribuímos um método que usa thisa 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 um fechamento - uma função interna. 2)

mesa

O que guarda o futuro

Definidas no ECMA Script 6 , as funções de seta adotam a thisligação do escopo anexo (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 estão desativando o thismecanismo tradicional em favor de um escopo lexical mais amplamente compreendido. (1)


Referências:

  1. Protótipos this & Object , de Kyle Simpson. © 2014 Soluções Getify.
  2. javascriptissexy.com - http://goo.gl/pvl0GX
  3. Angus Croll - http://goo.gl/Z2RacU
carlodurso
fonte
16

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

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

Então se eu fiz

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

element.onclick = someKindOfFunction;

thisse referiria ao objeto elemento. Mas tenha cuidado, muitas pessoas cometem esse erro.

<element onclick="someKindOfFunction()">

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

Seph
fonte
15

Todo contexto de execução em javascript possui um parâmetro this que é definido por:

  1. Como a função é chamada (incluindo como método de objeto, uso de call and apply , uso de new )
  2. Uso de bind
  3. Lexicamente para funções de seta (elas adotam o presente contexto de execução externa)
  4. Se o código está no modo estrito ou não estrito
  5. Se o código foi chamado usando eval

Você pode definir o valor disso 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, esse valor da função é o elemento DOM.

O jQuery torna isso trivial mudar com o jQuery.proxy.

estúpido
fonte
9
É um pouco mais correto dizer que toda chamada de função tem um escopo. Em outras palavras, o que está confuso sobre thisem Javascript é que é não uma propriedade intrínseca da própria função, mas sim um artefato da maneira como a função é invocada.
Pointy
@pointy obrigado. o que causa mais confusão sobre isso em js é o fato de que em todas as linguagens usadas anteriormente (c #, c ++), - isso não pode ser manipulado n sempre aponta para a instância do objeto, enquanto em js depende e pode ser alterado ao chamar funções usando func.call, func.bindetc. - Sushil
Sushil
2
thisse não referenciar o escopo de uma função. thisfará referência a um objeto específico (ou possivelmente undefined), que, como você disse, pode ser alterado usando.call() ou .apply(). O escopo de uma função é (essencialmente, quando simplificado) a quais variáveis ​​ele tem acesso, e isso depende inteiramente de onde a função é declarada e não pode ser alterada.
Nnnnnn
@ Pointy: "É um pouco mais correto dizer que toda chamada de função tem um escopo." Ainda mais correto dizer que funções (e agora blocos) têm escopo , chamadas de função têm contexto . Escopo define quais são os identificadores que podem ser usados ​​pelo código nesse escopo. O contexto define a que esses identificadores estão vinculados.
TJ Crowder
1
"Qualquer que seja esse escopo, é referenciado por" this "." Não, thise o escopo não tem nada a ver um com o outro no ES5 e antes (por exemplo, quando esta resposta foi escrita). No ES2015 (também conhecido como ES6), thise o escopo estão relacionados de uma maneira bastante mínima: as funções de seta wrt (othis em uma seta é herdada de seu escopo anexo), mas thisnunca se refere a um escopo.
TJ Crowder
10

Aqui está uma boa fonte de thisin JavaScript.

Aqui está o resumo:

  • global isso

    Em um navegador, no escopo global, thisé 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 a repl, thisé o namespace principal. 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

    Na nodeexecução 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ência no 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 newothis será um novo contexto, ela não fará referência ao global 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>
  • protótipo isso

As funções que você cria se tornam objetos de função. Eles obtêm automaticamente uma prototypepropriedade especial , à qual você pode atribuir valores. Quando você cria uma instância chamando sua função comnew você obtém acesso aos valores que você atribuiu à 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ê deseja que as instâncias tenham suas próprias matrizes, crie-as 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 []
  • objetar isso

Você pode usar thisem qualquer função de um objeto para se referir a outras propriedades desse objeto. 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 isso

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ê seja 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 this

Atributos HTML internos nos quais você pode colocar JavaScript, thisé 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 a leitura e gravação de valores thissem consultar 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, se thisrefere 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>
zangw
fonte
9

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

Em duas palavras, thisno 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 (essa tentativa terminará com 'Mão esquerda inválida lado na mensagem de atribuição.

Para manipuladores de eventos: os manipuladores de eventos em linha, como, por exemplo <element onclick="foo">, substituem quaisquer outros manipuladores anexados anteriormente e antes, portanto, tenha cuidado e é melhor evitar a delegação de eventos inline. 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)">
Arman McHitarian
fonte
9

Há muita confusão sobre como "essa palavra-chave " é interpretada em JavaScript. Esperemos que este artigo repouse todos aqueles que descansam de uma vez por todas. E muito mais. Por favor, leia o artigo inteiro 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, qual é 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 "Non Bound Function" (ou seja, uma função que não foi vinculada pela chamada functionName.bind )
  3. Chamada interna "Função não vinculada" indireta através de functionName.call e functionName.apply
  4. Chamada interna de "Função vinculada" (ou seja, uma função que foi vinculada ao chamar functionName.bind )
  5. Durante a criação de objetos por meio de "novo"
  6. Manipulador de eventos DOM Inline interno

A seguir, descreve cada um desses contextos, um por um:

  1. Contexto Global (isto é, Fora de todas as funções):

    Fora de todas as funções (isto é, no contexto global), o "objeto atual" (e, portanto, o valor de "isto" ) é sempre o objeto "janela" dos navegadores.

  2. Chamada interna direta de "Função não vinculada" :

    Dentro de uma chamada direta de "Função não vinculada", o objeto que chamou a chamada de função se torna o "objeto atual" (e, portanto, o valor de "this" ). Se uma função é chamada sem um objeto atual explícito , o objeto atual é o objeto "window" (para o modo não estrito) ou indefinido (para o modo estrito). Qualquer função (ou variável) definida no Contexto Global torna-se automaticamente uma propriedade do objeto "janela". Por exemplo, suponha que a função seja definida no Contexto Global como

    function UserDefinedFunction(){
        alert(this)
        }

    torna-se propriedade do objeto de janela, como se você o tivesse definido como

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

    No "Modo não estrito", chamar / chamar esta função diretamente por meio de "UserDefinedFunction ()" a chamará automaticamente como "window.UserDefinedFunction ()" making "window" como o "objeto atual" (e, portanto, o valor de " " ) em " UserDefinedFunction ". Invocar esta função no" Modo Não Rigoroso "resultará nos seguintes

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

    Em "modo estrito", chamando / Invocando a função diretamente através de "UserDefinedFunction ()" irá "NÃO" automaticamente chamar / invocá-la como "window.UserDefinedFunction ()" .Hence o "objeto atual" (e o valor de "isto" ) em "UserDefinedFunction" será indefinido . A invocação desta função no "Modo estrito" resultará nos seguintes

    UserDefinedFunction() // displays undefined

    No entanto, invocá-lo explicitamente usando o objeto window resultará nas seguintes

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

    Vejamos outro exemplo. Por favor, olhe o código a seguir

     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

    No exemplo acima, vemos que quando "UserDefinedFunction" foi chamado por meio de o1 , "this" assume o valor de o1 e o valor de suas propriedades "a" e "b" são exibidos. O valor de "c" e "d" foi mostrado como indefinido, pois o1 não define essas propriedades

    Da mesma forma, quando "UserDefinedFunction" foi invocado através o2 , "este" toma o valor de O2 e o valor das suas propriedades de "c" e "d" obter displayed.The valor de "a" e "b" foram mostrados como indeterminado como o2 faz não define essas propriedades.

  3. Chamada interna "Função não vinculada" indireta através da functionName.call e functionName.apply :

    Quando uma "Função não vinculada" é chamada por meio de functionName.call ou functionName.apply , o "objeto atual" (e, portanto, o valor de "this" ) é definido como o valor do parâmetro "this" (primeiro parâmetro) passado para chamar / aplicar . O código a seguir demonstra o mesmo.

    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

    O código acima mostra claramente que o valor "this" para qualquer "Função NÃO Limitada" pode ser alterado através de chamada / aplicação . Além disso, se o parâmetro "this" não for explicitamente passado para chamar / aplicar , "objeto atual" (e, portanto, o valor de "this") será definido como "window" no modo Non strict e "undefined" no modo strict.

  4. Dentro da chamada "Função vinculada" (ou seja, uma função que foi vinculada ao chamar functionName.bind ):

    Uma função vinculada é uma função cujo valor "this" foi corrigido. O código a seguir demonstrou como "isso" funciona em caso de função vinculada

    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

    Conforme indicado no código acima, "este" valor para qualquer "Função vinculada" NÃO PODE ser alterado através de chamada / aplicação . Além disso, se o parâmetro "this" não for explicitamente passado para ligação, o "objeto atual" (e, portanto, o valor de "this" ) será definido como "window" no modo Non strict e "undefined" no modo strict. Mais uma coisa. A ligação de uma função já vinculada não altera o valor "this" . Ele permanece definido como o valor definido pela primeira função de ligação.

  5. Durante a criação de objetos por meio de "novo" :

    Dentro de uma função construtora, o "objeto atual" (e, portanto, o valor de "this" ) faz referência ao objeto que está sendo criado no momento por meio de "novo", independentemente do status de ligação da função. No entanto, se o construtor for uma função vinculada, ele será chamado com um conjunto predefinido de argumentos, conforme definido para a função vinculada.

  6. Manipulador de eventos DOM interno do Inline :

    Veja o seguinte snippet HTML

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

    O "this" nos exemplos acima se refere ao elemento "button" e ao elemento "div", respectivamente.

    No primeiro exemplo, a cor da fonte do botão deve ser definida em branco quando ele é clicado.

    No segundo exemplo, quando o elemento "div" é clicado, ele deve chamar a função OnDivClick com seu segundo parâmetro referenciando o elemento div clicado. No entanto, o valor "this" no OnDivClick NÃO DEVE referenciar o elemento div clicado . Ele deve ser definido como o "objeto de janela" ou "indefinido" nos modos Não restrito e Rigoroso, respectivamente (se OnDivClick for uma função não acoplada ) ou definido como um valor Limite predefinido (se OnDivClick for uma função vinculada )

A seguir, resume o artigo inteiro

  1. No contexto global "isso" sempre se refere ao objeto "janela"

  2. Sempre que uma função é invocada, ela é invocada no contexto de um objeto ( "objeto atual" ). Se o objeto atual não for fornecido explicitamente, o objeto atual é o "objeto de janela" no modo NÃO estrito e "indefinido" no modo estrito por padrão.

  3. O valor "this" dentro de uma função Non Bound é a referência ao objeto no contexto em que a função é invocada ( "objeto atual" )

  4. O valor "this" em uma função Non Bound pode ser substituído por chamada e aplicar métodos da função.

  5. O valor "this" é fixo para uma função Limitada e não pode ser substituído por chamar e aplicar métodos da função.

  6. A função de ligação e já vinculada não altera o valor "this". Ele permanece definido como o valor definido pela primeira função de ligação.

  7. O valor "this" dentro de um construtor é o objeto que está sendo criado e inicializado

  8. O valor "this" em um manipulador de eventos DOM embutido é referência ao elemento para o qual o manipulador de eventos é fornecido.

Arup Hore
fonte
9

Provavelmente, o artigo mais detalhado e abrangente sobre thisé o seguinte:

Explicação suave da palavra-chave 'this' em JavaScript

A idéia subjacente thisé entender que os tipos de chamada de função têm uma importância significativa na configuração de thisvalor.


Ao ter problemas para identificar this, não se pergunte:

De onde é thistirado ?

mas não pergunte a si mesmo:

Como a função é invocada ?

Para uma função de seta (caso especial de transparência de contexto), pergunte-se:

Qual valor tem thisonde a função de seta é definida ?

Essa mentalidade é correta ao lidar com thise evita dores de cabeça.

Dmitri Pavlutin
fonte
Além de criar um link para o seu blog, talvez você possa se aprofundar um pouco mais em como essas perguntas ajudam alguém a entender a thispalavra - chave?
Magnus Lind Oxlund
7

Esta é a melhor explicação que eu já vi: Entenda JavaScripts isso com o Clarity

A referência a esta SEMPRE se refere (e mantém o valor de) um objeto - um objeto singular - e geralmente é usada dentro de uma função ou método, embora possa ser usada fora de uma função no escopo global. Observe que, quando usamos o modo estrito, isso mantém o valor de indefinido em funções globais e em funções anônimas que não estão vinculadas a nenhum objeto.

Existem quatro cenários em que isso pode ser confuso:

  1. Quando passamos um método (que usa isso ) como argumento para ser usado como uma função de retorno de chamada.
  2. Quando usamos uma função interna (um fechamento). É importante observar que o fechamento não pode acessar essa variável da função externa usando a palavra-chave this, porque a variável this é acessível apenas pela própria função, não por funções internas.
  3. Quando um método que depende disso é atribuído a uma variável entre contextos, nesse caso, ele faz referência a outro objeto que não o pretendido originalmente.
  4. Ao usar isso junto com a ligação, aplique e chame métodos.

Ele fornece exemplos de código, explicações e soluções, que achei muito úteis.

James Drinkard
fonte
6

Em termos pseudoclássicos, o modo como muitas palestras ensinam a palavra-chave 'this' é como um objeto instanciado por um construtor de classe ou objeto. Cada vez que um novo objeto é construído a partir de uma classe, imagine que, sob o capô, uma instância local de um objeto 'this' seja criada e retornada. Lembro que ensinou assim:

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;
mrmaclean89
fonte
5

thisé um dos conceitos incompreendidos no JavaScript porque se comporta de maneira um pouco diferente de um lugar para outro. Simplesmente, thisrefere-se ao "proprietário" da função que estamos executando atualmente .

thisajuda a obter o objeto atual (também conhecido como contexto de execução) com o qual trabalhamos. Se você entender em qual objeto a função atual está sendo executada, poderá entender facilmente qual thisé a corrente.

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

Acima, criamos 3 variáveis ​​com o mesmo nome 'val'. Um no contexto global, um dentro de obj e o outro dentro de InnerMethod of obj. O JavaScript resolve identificadores dentro de um contexto específico, subindo a cadeia de escopo de local para global.


Poucos lugares onde thispodem ser diferenciados

Chamando um método de um objeto

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

Quando a linha1 é executada, o JavaScript estabelece um contexto de execução (EC) para a chamada de função, configurando thiso objeto referenciado pelo que veio antes do último "." . Então, na última linha, você pode entender que a()foi executado no contexto global, que é o window.

With Constructor

this pode ser usado para se referir ao objeto que está sendo criado

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

Quando new Person()é executado, um objeto completamente novo é criado. Personé chamado e thisestá definido para referenciar esse novo objeto.

Chamada de função

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 

Se faltarmos a newpalavra-chave, whatIsThisrefere-se ao contexto mais global que ela pode encontrar ( window)

Com manipuladores de eventos

Se o manipulador de eventos estiver embutido, thisrefere-se ao objeto global

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

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

Ao adicionar o manipulador de eventos por meio do JavaScript, thisrefere-se ao elemento DOM que gerou o evento.


Nipuna
fonte
5

O valor "this" depende do "contexto" no qual a função é executada. O contexto pode ser qualquer objeto ou o objeto global, ou seja, janela.

Portanto, a semântica "disso" é diferente das linguagens tradicionais de POO. E isso causa problemas: 1. quando uma função é passada para outra variável (provavelmente, um retorno de chamada); e 2. quando um fechamento é invocado a partir de um método membro de uma classe.

Nos dois casos, isso é definido como janela.

Trombe
fonte
3

Whould esta ajuda? (A maior parte da confusão de 'this' no javascript é proveniente do fato de que geralmente não está vinculado ao seu objeto, mas do escopo de execução atual - isso pode não ser exatamente como ele funciona, mas sempre é assim para mim - veja o artigo para uma explicação completa)

Simon Groenewolt
fonte
1
Seria melhor dizer que está vinculado " ao atual contexto de execução ". Exceto ES6 (rascunho) altera isso com as funções de seta, onde isso é resolvido no contexto de execução externa.
RobG
3

Um pouco de informação sobre esta palavra - chave

Vamos registrar a thispalavra-chave no console no escopo global sem mais código, mas

console.log(this)

No cliente / navegador, a this palavra-chave é um objeto global que éwindow

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

e

Em Server / Node / Javascript, a this palavra-chave de tempo de execução também é um objeto global que émodule.exports

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

Lembre-se exportsé apenas uma referência amodule.exports

unclexo
fonte
1

este uso para o escopo assim

  <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>

o valor de txt1 e txt é o mesmo no exemplo acima $ (this) = $ ('# tbleName tbody tr') é o mesmo

PRADEEP SINGH Chundawat
fonte
1

Eu tenho uma opinião diferente thisdas outras respostas que espero que sejam úteis.

Uma maneira de observar o JavaScript é ver que há apenas uma maneira de chamar uma função 1 . Isto é

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

Sempre há algum valor fornecido objectForThis.

Tudo o resto é açúcar sintático para functionObject.call

Portanto, tudo o mais pode ser descrito pela forma como ele se traduz functionObject.call.

Se você acabou de chamar uma função, então thisé o "objeto global" que no navegador é a janela

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

foo();  // this is the window object

Em outras palavras,

foo();

foi efetivamente traduzido para

foo.call(window);

Observe que, se você usar o modo estrito, thisseráundefined

'use strict';

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

foo();  // this is the window object

que significa

Em outras palavras,

foo();

foi efetivamente traduzido para

foo.call(undefined);

Em JavaScript, existem operadores como +e -e *. Há também o operador de ponto que é.

o . operador, quando usado com uma função à direita e um objeto à esquerda, significa efetivamente "passar o objeto quanto thisà função".

Exemplo

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

bar.foo();  // this is bar

Em outras palavras bar.foo() traduz emconst temp = bar.foo; temp.call(bar);

Observe que não importa como a função foi criada (principalmente ...). Tudo isso produzirá os mesmos resultados

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

Novamente, todos esses são apenas açúcar sintático para

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

Uma outra ruga é a cadeia de protótipos. Quando você usa a.bJavaScript primeiros olhares sobre o objeto referenciado diretamente por apara a propriedade b. Se bnão for encontrado no objeto, o JavaScript procurará no protótipo do objeto para encontrarb .

Existem várias maneiras de definir o protótipo de um objeto, o mais comum em 2019 é a classpalavra - chave. Para os propósitos de thisembora isso não importe. O que importa é que, ao procurar no objeto apor propriedade, bse encontrar propriedade bno objeto ou em sua cadeia de protótipos, se bacabar sendo uma função, as mesmas regras acima se aplicam. As breferências de função serão chamadas usando o callmétodo e passandoa como objectForThis, como mostrado no topo desta resposta.

Agora. Vamos imaginar que criamos uma função que define explicitamente thisantes de chamar outra função e depois a chamamos com o .operador (ponto)

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

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

const obj = {
  bar,
};

obj.bar();  

Após a tradução para usar call, obj.bar()torna-se const temp = obj.bar; temp.call(obj);. Quando entramos na barfunção que chamamos, foomas passamos explicitamente outro objeto para objectForThis; assim, quando chegamos ao foo, thisesse objeto interno.

Isto é o que ambos binde =>funções efetivamente fazer. Eles são mais açúcar sintático. Eles efetivamente constroem uma nova função invisível exatamente como baracima, que thisé definida explicitamente antes de chamar qualquer função especificada. No caso de bind, thisé definido como o que você passa 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'});

Observe que, se functionObject.bindnão existisse, poderíamos fazer nossos próprios assim

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

e então poderíamos chamar assim

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

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

Funções de seta, o =>operador é açúcar sintático para ligação

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

é o mesmo que

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

Assim como bind, uma nova função invisível é criada que chama a função fornecida com um valor vinculado, objectForThismas, ao contrário binddo objeto a ser vinculado, está implícita. É o que thisacontece quando o =>operador é usado.

Então, assim como as regras acima

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()traduz para const temp = obj.foo; temp.call(obj);que meios o operador de seta dentro foose ligará obja uma nova função invisível e retornará a nova função invisível à qual está atribuída b. b()funcionará como sempre, b.call(window)ou b.call(undefined)chama a nova função invisível foocriada. Essa função invisível ignora o thispassado para ele e passa objcomo objectForThis` para a função de seta.

O código acima se traduz em

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 é outra função semelhante acall

functionName.apply(objectForThis, arrayOfArgs);

Mas a partir do ES6 conceitualmente, você pode até traduzir isso para

functionName.call(objectForThis, ...arrayOfArgs);
gman
fonte
0

Resumo thisJavascript:

  • O valor de thisé determinado pela forma como a função não é chamada, onde foi criada!
  • Normalmente, o valor de thisé determinado pelo objeto que resta do ponto. ( windowno espaço global)
  • Nos ouvintes de eventos, o valor de this refere-se ao elemento DOM no qual o evento foi chamado.
  • Quando a função é chamada com a newpalavra-chave, o valor de thisrefere-se ao objeto recém-criado
  • Você pode manipular o valor de thiscom as funções: call, apply,bind

Exemplo:

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
              
             

Exemplo de ouvintes de eventos:

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>

Construtor de exemplo:

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.

Willem van der Veen
fonte
0

Para entender "isso" corretamente, é preciso entender o contexto, o escopo e a diferença entre eles.

Escopo : no escopo javascript está relacionado à visibilidade das variáveis, o escopo é obtido com o uso da função. (Leia mais sobre o escopo)

Contexto : o contexto está relacionado aos objetos. Refere-se ao objeto ao qual uma função pertence. Quando você usa a palavra-chave “this” do JavaScript, ela se refere ao objeto ao qual a função pertence. Por exemplo, dentro de uma função, quando você diz: "this.accoutNumber", você está se referindo à propriedade "accoutNumber", que pertence ao objeto ao qual essa função pertence.

Se o objeto "myObj" possui um método chamado "getMyName", quando a palavra-chave JavaScript "this" é usada dentro de "getMyName", refere-se a "myObj". Se a função "getMyName" foi executada no escopo global, "this" se refere ao objeto de janela (exceto no modo estrito).

Agora vamos ver um exemplo:

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

Executar um código acima na saída do navegador: insira a descrição da imagem aqui

De acordo com a saída que você está dentro do contexto do objeto de janela, também é visível que o protótipo de janela se refere ao objeto.

Agora vamos tentar dentro de uma função:

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

Resultado:

insira a descrição da imagem aqui A saída é a mesma porque registramos a variável 'this' no escopo global e no escopo funcional, não alteramos o contexto. Nos dois casos, o contexto era o mesmo, relacionado ao objeto viúvo .

Agora vamos criar nosso próprio objeto. Em javascript, você pode criar um objeto de várias maneiras.

 <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>

Resultado: insira a descrição da imagem aqui

Portanto, a partir do exemplo acima, descobrimos que a palavra-chave 'this' se refere a um novo contexto relacionado ao myObj, e o myObject também possui uma cadeia de protótipos para Object.

Vamos dar outro exemplo:

<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>

saída: faz sentido, certo? (leia comentários) insira a descrição da imagem aqui

Se você tiver problemas para entender o exemplo acima, tente com nosso próprio retorno de chamada;

<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>

resultado: insira a descrição da imagem aqui

Agora vamos entender o escopo, o Self, o IIFE e ISTO como se comporta

       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> 

Saída é bastante impressionante, certo? insira a descrição da imagem aqui

senhor
fonte
-1

Resposta simples:

A palavra-chave "this" depende sempre do contexto da chamada. Eles são mencionados abaixo.

  1. A FUNÇÃO É CHAMADA COM NOVA PALAVRA-CHAVE

    Se a função for chamada com a palavra-chave NEW, ESTA será vinculada ao objeto recém-criado.

    function Car(){
      this.name="BMW";
    }
    const myCar=new Car();
    myCar.name; // output "BMW"

    Acima, isso será vinculado ao objeto 'myCar'

  2. A FUNÇÃO É CHAMADA EXPLICITAMENTE USANDO MÉTODOS DE CHAMADA E APLICAÇÃO.

    Nesse caso, ESTE será vinculado ao objeto que é explicitamente passado para a função.

    var obj1={"name":"bond"};
    function printMessage(msg){
        return msg+" "+this.name;
    }
    const message=printMessage.call(obj1,"my name is ");
    console.log(message); //HERE THIS WILL BE BOUND TO obj1 WHICH WE PASSED EXPLICITLY. SAME FOR APPLY METHOD ALSO.
  3. SE A FUNÇÃO É CHAMADA COM OBJETO IMPLICITAMENTE, ENTÃO ESTE SERÁ LIMITADO AO OBJETO

    var obj1={
       "name":"bond",
        getName: function () {
                    return this.name;
                 }
    };
    const newname=obj1.getName();
    console.log(newname); //HERE THIS WILL BE BOUND TO obj1(WHITCHEVER OBJECT IS MENTIONED BEFORE THE DOT THIS WILL BE BOUND TO THAT)
  4. QUANDO A FUNÇÃO É CHAMADA SEM QUALQUER CONTEXTO, ENTÃO ISSO SERÁ LIMITADO A OBJETO GLOBAL

    const util = {
       name: 'Utility',
       getName: function () {
                    return this.name;
    };
    
    const getName=util.getName;
    const newName=getName();
    console.log(newName); // IF THIS EXECUTED IN BROWSER THIS WILL BE  BOUND TO WINDOW OBJECT. IF THIS EXECUTED IN SERVER THIS WILL BE BOUND TO GLOBAL OBJECT
  5. NO MODO ESTRITO, ESTE NÃO SERÁ DEFINIDO

    function setName(name){
        "use strict"
        return this.name;
    }
    setName(); //WILL BE ERROR SAYING name IS UNDEFINED. 
PALLAMOLLA SAI
fonte