Como passo esse contexto para uma função?

213

Eu pensei que isso seria algo que eu poderia facilmente pesquisar no Google, mas talvez eu não esteja fazendo a pergunta certa ...

Como definir o que "isso" se refere em uma determinada função javascript?

por exemplo, como na maioria das funções do jQuery, como:

$(selector).each(function() {
   //$(this) gives me access to whatever selector we're on
});

Como escrevo / chamo minhas próprias funções independentes que possuem uma referência "this" apropriada quando chamada? Eu uso o jQuery; portanto, se houver uma maneira específica de fazê-lo, isso seria o ideal.

user126715
fonte
Possível duplicata: stackoverflow.com/questions/520019/…
user123444555621
Eu sei que isto é uma questão antiga, mas para outros desembarque aqui ver jQuery$.proxy
RyBolt

Respostas:

302

Javascripts .call()e .apply()métodos permitem definir o contexto de uma função.

var myfunc = function(){
    alert(this.name);
};

var obj_a = {
    name:  "FOO"
};

var obj_b = {
    name:  "BAR!!"
};

Agora você pode ligar para:

myfunc.call(obj_a);

O que alertaria FOO. Ao contrário, a passagem obj_balertaria BAR!!. A diferença entre .call()e .apply()é que .call()leva uma lista separada por vírgula se você estiver passando argumentos para sua função e .apply()precisa de uma matriz.

myfunc.call(obj_a, 1, 2, 3);
myfunc.apply(obj_a, [1, 2, 3]);

Portanto, você pode facilmente escrever uma função hookusando o apply()método Por exemplo, queremos adicionar um recurso ao .css()método jQuerys . Podemos armazenar a referência da função original, substituir a função pelo código personalizado e chamar a função armazenada.

var _css = $.fn.css;
$.fn.css = function(){
   alert('hooked!');
   _css.apply(this, arguments);
};

Como o argumentsobjeto mágico é um array como um objeto, podemos apenas passá-lo para apply(). Dessa forma, garantimos que todos os parâmetros sejam passados ​​para a função original.

jAndy
fonte
4
Apenas um boato divertido: se você precisar chamar a função repetidamente em referência a obj_a, por exemplo, poderá criar uma cópia dela var boud_myfunc = myfunc.bind(obj_a)e simplesmente chamar bound_myfunc()conforme necessário.
Wattart 15/16 /
44

Usefunction.call :

var f = function () { console.log(this); }
f.call(that, arg1, arg2, etc);

Onde thatestá o objeto que você deseja que thisa função esteja.

palswim
fonte
1
functioné uma palavra-chave reservada; considere atualizar sua resposta para incluir uma função nomeada, pois function.call(...)não é JavaScript válido.
Daniel Allen
1
@ Danielielen: Sem a definição de qualquer nome de função de amostra que eu forneça, o código ainda gerará um erro JS. Mas atualizei o nome da função de amostra.
palswim 15/09/17
16

O jQuery usa um .call(...)método para atribuir o nó atual à thisfunção que você passa como parâmetro.

EDITAR:

Não tenha medo de olhar dentro do código do jQuery quando tiver alguma dúvida, está tudo em Javascript claro e bem documentado.

ou seja: a resposta a esta pergunta está na linha 574,
callback.call( object[ name ], name, object[ name ] ) === false

Microfone
fonte
12

Você pode usar a função de ligação para definir o contexto de thisdentro de uma função.

function myFunc() {
  console.log(this.str)
}
const myContext = {str: "my context"}
const boundFunc = myFunc.bind(myContext);
boundFunc(); // "my context"
Scott Jungwirth
fonte
12

Outro exemplo básico:

Não está funcionando:

var img = new Image;
img.onload = function() {
   this.myGlobalFunction(img);
};
img.src = reader.result;

Trabalhando:

var img = new Image;
img.onload = function() {
   this.myGlobalFunction(img);
}.bind(this);
img.src = reader.result;

Então, basicamente: basta adicionar .bind (this) à sua função

Joery
fonte
Essa deve ser a resposta aceita. Sintaxe muito mais fácil, muito mais fácil na mente ... bom trabalho Joery
nenea 18/04/19