Establecer "esta" variable fácilmente?

139

Tengo una buena comprensión de Javascript, excepto que no puedo encontrar una buena manera de establecer la variable "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

¿Hay alguna manera de hacer esto sin las últimas 4 líneas? Es bastante molesto ... He intentado vincular una función anónima, que pensé que era hermosa e inteligente, pero fue en vano:

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, pasar la variable a myFunction es una opción ... pero ese no es el punto de esta pregunta.

Gracias.

Erik Philips
fuente

Respuestas:

221

Hay dos métodos definidos para todas las funciones en JavaScript call(), y apply(). La sintaxis de la función se ve así:

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

Lo que estas funciones hacen es llamar a la función que se invocaron en, asignando el valor del objeto parámetro a este .

var myFunction = function(){
    alert(this.foo_variable);
}
myFunction.call( document.body );
Por tu propio bien
fuente
3
Además, si está usando jQuery, puede usarlo $.proxy(function, element)para que cada vez que se llame a esa función, esté en el contexto del elemento. api.jquery.com/jquery.proxy
Trevin Avery
Otro método útil es.bind()
Soroush Falahati
55

Creo que estás buscando call:

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

Esto llama myFunctioncon thisset to obj.

También existe el método ligeramente diferente apply, que toma los parámetros de la función como una matriz:

myFunction.apply(obj, [arg1, arg2, ...]);
algo
fuente
1
Consulte la sección 15.3.4.3, 15.3.4.4 y 10.1.8 en la especificación del lenguaje ECMAScript: ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
algunos
18

Si desea 'almacenar' el thisvalor en una función para poder llamarlo sin problemas más tarde (por ejemplo, cuando ya no tenga acceso a ese valor), puede bindhacerlo (aunque no está disponible en todos los navegadores):

var bound = func.bind(someThisValue);

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

bound(); // will call with someThisValue as 'this'
pimvdb
fuente
77
FYI bindaparentemente está disponible en IE9 +, FF4 +, Safari 5.1.4+ y Chrome 7+ (fuente) . También puede llamar a bind directamente en una función anónima:var myFunction = function(){ /* this = something */ }.bind(something);
Adam
1

Mi búsqueda sobre cómo vincular thisme trajo aquí, así que estoy publicando mis hallazgos: en 'ECMAScript 2015' también podemos configurar esto léxicamente usando las funciones de flecha para.

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

En vez 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);
}

Ahora podemos hacer:

function Person(){
  this.age = 0;

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

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

Establecer la thispalabra clave en javascript.

Javascript tiene 3 métodos integrados para configurar la thispalabra clave convenientemente. Todos están ubicados en el Function.prototypeobjeto para que cada función pueda usarlos (ya que cada función hereda de este prototipo a través de la herencia prototípica). Estas funciones son las siguientes:

  1. Function.prototype.call(): Esta función toma el objeto que desea usar como thisprimer argumento. Entonces, el resto de los argumentos son los argumentos respectivos de la función que se llama.
  2. Function.prototype.apply(): Esta función toma el objeto que desea usar como thisprimer argumento. Entonces, el segundo argumento es una matriz que contiene los valores de los argumentos de la función que se llama (el primer elemento de la matriz es el primer argumento de la función, el segundo argumento de la matriz es el segundo argumento de la función, etc.).
  3. Function.prototype.bind(): Esta función devuelve una nueva función que tiene un valor diferente de this. Toma el objeto que desea establecer como thisvalor como primer argumento y luego devuelve un nuevo objeto de función.

Diferencia entre llamar / aplicar y vincular:

  • cally applyson similares en el hecho de que llaman inmediatamente a la función (con un valor predefinido de this)
  • bindes diferente cally applyen el hecho de que esta función devuelve una nueva función con un enlace diferente del thisvalor.

Ejemplos:

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
fuente