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

139

У меня довольно хорошее представление о 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 - это вариант ... но вопрос не в этом.

Спасибо.

Эрик Филипс
источник

Ответы:

223

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

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

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

var myFunction = function(){
    alert(this.foo_variable);
}
myFunction.call( document.body );
Для твоего блага
источник
3
Кроме того, если вы используете jQuery, вы можете использовать его $.proxy(function, element)так, чтобы всякий раз, когда эта функция вызывается, она будет в контексте element. api.jquery.com/jquery.proxy
Тревин Эйвери
Еще один полезный метод.bind()
Соруш Фалахати
55

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

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

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

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

myFunction.apply(obj, [arg1, arg2, ...]);
что-то
источник
1
См. Разделы 15.3.4.3, 15.3.4.4 и 10.1.8 в Спецификации языка ECMAScript: ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
примерно
18

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

var bound = func.bind(someThisValue);

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

bound(); // will call with someThisValue as 'this'
pimvdb
источник
7
FYI, bindпо-видимому, доступен в IE9 +, FF4 +, Safari 5.1.4+ и Chrome 7+ (источник) . Вы также можете вызвать bind непосредственно для анонимной функции:var myFunction = function(){ /* this = something */ }.bind(something);
Адам,
1

Мои поиски о том, как привязать, 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();
Даниэль Соколовски
источник
1

Установка 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похожи тем, что сразу вызывают функцию (с предопределенным значением this)
  • bindотличается от callи applyтем, что эта функция возвращает новую функцию с другой привязкой 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');

Виллем ван дер Вин
источник