Легко установить переменную "this"?

У меня довольно хорошее понимание Javascript, за исключением того, что я не могу найти хороший способ установить переменную "this". Рассмотрим:

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

Есть ли способ сделать это без последних 4 строк? Это довольно раздражает... Я пытался привязать анонимную функцию, которая, как я думал, была красивой и умной, но безрезультатно:

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.

Очевидно, что передача переменной в myFunction является опцией... но это не точка этого вопроса.

Спасибо.

Ответ 1

Для всех функций в JavaScript существуют два метода: call() и apply(). Синтаксис функции выглядит так:

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

Что эти функции делают, это вызвать функцию, на которую они были вызваны, присваивая значение параметра объекта этому.

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

Ответ 2

Я думаю, что вы ищете call:

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

Это вызывает myFunction с this, установленным в obj.

Существует также несколько иной метод apply, который принимает параметры функции как массив:

myFunction.apply(obj, [arg1, arg2, ...]);

Ответ 3

Если вы хотите "сохранить" значение this для функции, чтобы вы могли ее легко переписать (например, когда у вас больше нет доступа к этому значению), вы можете bind его (недоступно во всех браузерах):

var bound = func.bind(someThisValue);

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

bound(); // will call with someThisValue as 'this'

Ответ 4

Мой поиск о том, как связать this, привел меня сюда, поэтому я публикую свои выводы: в "ECMAScript 2015" мы также можем установить это лексически, используя функции стрелок.

Смотрите: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Вместо:

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

Теперь мы можем сделать:

function Person(){
  this.age = 0;

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

var p = new Person();

Ответ 5

Установка this ключевого слова в javascript.

Javascript имеет 3 встроенных метода для удобного задания this ключевого слова. Все они расположены на объекте Function.prototype поэтому каждая функция может их использовать (поскольку каждая функция наследуется от этого прототипа через прототипное наследование). Эти функции следующие:

  1. Function.prototype.call(): Эта функция принимает объект, который вы хотите использовать в качестве this в качестве первого аргумента. Тогда остальные аргументы являются соответствующими аргументами вызываемой функции.
  2. Function.prototype.apply(): Эта функция принимает объект, который вы хотите использовать в качестве this в качестве первого аргумента. Тогда второй аргумент представляет собой массив, который содержит значения аргументов вызываемой функции (первый элемент массива - первый аргумент функции, второй аргумент массива - второй аргумент функции и т.д.).
  3. Function.prototype.bind(): Эта функция возвращает новую функцию, которая имеет другое значение this. Он принимает объект, который вы хотите установить как this значение в качестве первого аргумента, а затем возвращает новый объект функции.

Разница между вызовом/применением и привязкой:

  • call и apply аналогичны в том, что они сразу же вызывают функцию
  • bind отличается от этого тем, что эта функция возвращает новую функцию с другим привязкой к this значению.

Примеры:

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