¿Cómo paso el contexto a una función?

213

Pensé que esto sería algo que podría fácilmente googlear, pero tal vez no estoy haciendo la pregunta correcta ...

¿Cómo configuro todo lo que se refiere a "esto" en una determinada función de JavaScript?

por ejemplo, como con la mayoría de las funciones de jQuery como:

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

¿Cómo escribo / llamo a mis propias funciones independientes que tienen una referencia apropiada "this" cuando se llama? Yo uso jQuery, así que si hay una forma específica de jQuery de hacerlo, sería ideal.

usuario126715
fuente
Posible duplicado: stackoverflow.com/questions/520019/…
user123444555621
Sé que esta es una vieja pregunta, pero para otros que aterrizan aquí, ver jQuery$.proxy
RyBolt

Respuestas:

302

Los javascripts .call()y los .apply()métodos le permiten establecer el contexto para una función.

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

var obj_a = {
    name:  "FOO"
};

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

Ahora puedes llamar:

myfunc.call(obj_a);

Lo cual alertaría FOO. Al revés, pasar obj_balertaría BAR!!. La diferencia entre .call()y .apply()es que .call()toma una lista separada por comas si está pasando argumentos a su función y .apply()necesita una matriz.

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

Por lo tanto, puede escribir fácilmente una función hookutilizando el apply()método Por ejemplo, queremos agregar una función al .css()método jQuerys . Podemos almacenar la referencia de función original, sobrescribir la función con código personalizado y llamar a la función almacenada.

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

Dado que el argumentsobjeto mágico es una matriz como objeto, simplemente podemos pasarlo apply(). De esa forma, garantizamos que todos los parámetros pasan a la función original.

jAndy
fuente
44
Solo un dato divertido: si necesita llamar a la función repetidamente en referencia a obj_a, por ejemplo, puede crear una copia var boud_myfunc = myfunc.bind(obj_a)y simplemente llamar bound_myfunc()según sea necesario.
wbadart
44

Usofunction.call :

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

¿Dónde thatestá el objeto que desea thisen la función?

palswim
fuente
1
functiones una palabra clave reservada; considere actualizar su respuesta para incluir una función con nombre ya function.call(...)que no es JavaScript válido.
Daniel Allen
1
@DanielAllen: Sin la definición del nombre de la función de muestra que proporcionaría, el código aún arrojará un error JS. Pero actualicé el nombre de la función de muestra.
palswim
16

jQuery utiliza un .call(...)método para asignar el nodo actual al thisinterior de la función que pasa como parámetro.

EDITAR:

No tenga miedo de mirar dentro del código de jQuery cuando tenga dudas, todo está en JavaScript claro y bien documentado.

es decir: la respuesta a esta pregunta está alrededor de la línea 574,
callback.call( object[ name ], name, object[ name ] ) === false

Micrófono
fuente
12

Puede usar la función de vinculación para establecer el contexto thisdentro de una función.

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

Otro ejemplo básico:

No funciona:

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

Trabajando:

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

Básicamente: simplemente agregue .bind (this) a su función

Joery
fuente
Esta debería ser la respuesta aceptada. Sintaxis mucho más fácil, mucho más fácil en la mente ... buen trabajo Joery
nenea