Defina a variável "this" facilmente?

139

Eu tenho um bom entendimento de Javascript, exceto que não consigo descobrir uma boa maneira de definir a variável "this". Considerar:

var myFunction = function(){
    alert(this.foo_variable);
}

var someObj = document.body; //using body as example object
someObj.foo_variable = "hi"; //set foo_variable so it alerts

var old_fn = someObj.fn;   //store old value
someObj.fn = myFunction;   //bind to someObj so "this" keyword works
someObj.fn();              
someObj.fn = old_fn;       //restore old value

Existe uma maneira de fazer isso sem as últimas 4 linhas? É um pouco chato ... Tentei vincular uma função anônima, que achei bonita e inteligente, mas sem sucesso:

var myFunction = function(){
    alert(this.foo_variable);
}

var someObj = document.body;        //using body as example object
someObj.foo_variable = "hi";        //set foo_variable so it alerts
someObj.(function(){ fn(); })();    //fail.

Obviamente, passar a variável para myFunction é uma opção ... mas esse não é o objetivo desta pergunta.

Obrigado.

Erik Philips
fonte

Respostas:

221

Existem dois métodos definidos para todas as funções em JavaScript,, call()e apply(). A sintaxe da função é semelhante a:

call( /* object */, /* arguments... */ );
apply(/* object */, /* arguments[] */);

O que essas funções fazem é chamar a função na qual foram invocadas, atribuindo o valor do parâmetro do objeto a isso .

var myFunction = function(){
    alert(this.foo_variable);
}
myFunction.call( document.body );
Para o seu próprio bem
fonte
3
Além disso, se você estiver usando jQuery, poderá usá- $.proxy(function, element)lo para que, sempre que essa função for chamada, ela esteja no contexto do elemento. api.jquery.com/jquery.proxy
Trevin Avery
Outro método útil é.bind()
Soroush Falahati 16/06
55

Eu acho que você está procurando call:

myFunction.call(obj, arg1, arg2, ...);

Isso chama myFunctioncom thisdefinido como obj.

Há também o método ligeiramente diferente apply, que usa os parâmetros de função como uma matriz:

myFunction.apply(obj, [arg1, arg2, ...]);
sth
fonte
1
Consulte a seção 15.3.4.3, 15.3.4.4 e 10.1.8 no ECMAScript Language Specification: ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
alguns
18

Se você deseja 'armazenar' o thisvalor em uma função para que possa chamá-lo sem problemas mais tarde (por exemplo, quando você não tiver mais acesso a esse valor), poderá bindfazê-lo (embora não esteja disponível em todos os navegadores):

var bound = func.bind(someThisValue);

// ... later on, where someThisValue is not available anymore

bound(); // will call with someThisValue as 'this'
pimvdb
fonte
7
bindAparentemente, o FYI está disponível no IE9 +, FF4 +, Safari 5.1.4+ e Chrome 7+ (fonte) . Você também pode chamar bind diretamente em uma função anônima:var myFunction = function(){ /* this = something */ }.bind(something);
Adam
1

Minha pesquisa sobre como ligar thisme trouxe aqui, então estou postando minhas descobertas: No 'ECMAScript 2015', também podemos definir isso lexicamente usando as funções de seta para.

Consulte: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Ao invés de:

function Person() {
  setInterval(function growUp() {
    // The callback refers to the `self` variable of which
    // the value is the expected object.
    this.age++;
  }.bind(this), 1000);
}

Agora podemos fazer:

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++; // |this| properly refers to the person object
  }, 1000);
}

var p = new Person();
Daniel Sokolowski
fonte
0

Definindo a thispalavra - chave em javascript.

O Javascript possui 3 métodos internos para definir a thispalavra - chave de forma conveniente. Eles estão todos localizados no Function.prototypeobjeto para que todas as funções possam usá-los (já que todas as funções herdam deste protótipo por herança prototípica). Essas funções são as seguintes:

  1. Function.prototype.call(): Esta função pega o objeto que você deseja usar como thisprimeiro argumento. O restante dos argumentos são os respectivos argumentos da função que é chamada.
  2. Function.prototype.apply(): Esta função pega o objeto que você deseja usar como thisprimeiro argumento. Então o segundo argumento é uma matriz que contém os valores dos argumentos da função que é chamada (o primeiro elemento da matriz é o primeiro argumento da função, o segundo argumento da matriz é o segundo argumento da função etc.).
  3. Function.prototype.bind(): Esta função retorna uma nova função que possui um valor diferente de this. Ele pega o objeto que você deseja definir como thisvalor como primeiro argumento e, em seguida, retorna um novo objeto de função.

Diferença entre ligar / aplicar e ligar:

  • calle applysão semelhantes no fato de que eles chamam imediatamente a função (com um valor predefinido de this)
  • bindé diferente calle applyno fato de que essa função retorna uma nova função com uma ligação diferente do thisvalor.

Exemplos:

const thisObj = {
  prop1: 1,
  prop2: 2,
};

function myFunc(arg1, arg2) {
  console.log(this.prop1, this.prop2);
  console.log(arg1, arg2);
}

// first arg this obj, other arguments are the  
// respective arguments of the function
myFunc.call(thisObj, 'Call_arg1', 'Call_arg2');

// first arg this obj, other argument is an array which  
// are the respective arguments of the function
myFunc.apply(thisObj, ['Apply_arg1', 'Apply_arg2']);


// the bind method returns a new function with a different
// this context which is stored in the newMyFunc variable
const newMyFunc = myFunc.bind(thisObj);

// now we can call the function like a normal function 
newMyFunc('first', 'second');

Willem van der Veen
fonte