Как передать контекст this функции?

213

Я думал, что это будет то, что я мог бы легко гуглить, но, возможно, я не задаю правильный вопрос ...

Как мне установить, что "это" ссылается в данной функции JavaScript?

например, как с большинством функций jQuery, таких как:

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

Как мне написать / вызвать мои собственные автономные функции, которые имеют соответствующую ссылку «this» при вызове? Я использую jQuery, поэтому, если есть способ, специфичный для jQuery, это было бы идеально.

user126715
источник
Возможный дубликат: stackoverflow.com/questions/520019/…
user123444555621
Я знаю, что это старый вопрос, но для других посадки здесь смотрите jQuery$.proxy
RyBolt

Ответы:

303

Javascripts .call()и .apply()методы позволяют вам установить контекст для функции.

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

var obj_a = {
    name:  "FOO"
};

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

Теперь вы можете позвонить:

myfunc.call(obj_a);

Что бы предупредить FOO. Наоборот, прохождение obj_bпредупредит BAR!!. Разница между .call()и .apply()заключается в том, что .call()список разделяется запятыми, если вы передаете аргументы своей функции и.apply() нужен массив.

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

Следовательно, вы можете легко написать функцию hook, используя apply()метод. Например, мы хотим добавить функцию в .css()метод jQuerys . Мы можем сохранить исходную ссылку на функцию, переписать функцию с помощью специального кода и вызвать сохраненную функцию.

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

Поскольку магический argumentsобъект является массивом, похожим на объект, мы можем просто передать его apply(). Таким образом, мы гарантируем, что все параметры передаются исходной функции.

JANDY
источник
4
Просто забавный трюк: если вам нужно повторно вызывать функцию obj_a, например, по ссылке , вы можете создать ее копию var boud_myfunc = myfunc.bind(obj_a)и просто вызывать по bound_myfunc()мере необходимости.
wbadart
45

Используйтеfunction.call :

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

Где thatнаходится объект, который вы хотите thisв функции.

palswim
источник
1
functionявляется зарезервированным ключевым словом; рассмотрите возможность обновления вашего ответа для включения именованной функции, поскольку function.call(...)это недопустимый JavaScript.
Даниэль Аллен
1
@DanielAllen: без определения какого-либо примера имени функции, которое я предоставлю, код все равно выдаст ошибку JS. Но я обновил имя образца функции.
Palswim
16

JQuery использует .call(...) метод для назначения текущего узла thisвнутри функции, которую вы передаете в качестве параметра.

РЕДАКТИРОВАТЬ:

Не бойтесь заглядывать в код jQuery, когда у вас есть сомнения, все это в ясном и хорошо документированном Javascript.

то есть: ответ на этот вопрос находится вокруг строки 574,
callback.call( object[ name ], name, object[ name ] ) === false

микрофон
источник
12

Вы можете использовать функцию связывания, чтобы установить контекст thisвнутри функции.

function myFunc() {
  console.log(this.str)
}
const myContext = {str: "my context"}
const boundFunc = myFunc.bind(myContext);
boundFunc(); // "my context"
Скотт Юнгвирт
источник
12

Еще один базовый пример:

Не работает:

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

Работает:

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

Итак, в основном: просто добавьте .bind (this) к вашей функции

Joery
источник
Это должен быть принятый ответ. Намного легче синтаксис, намного проще для ума ... хорошая работа Joery
Nenea