#javascript
#javascript
Вопрос:
У меня есть некоторый код javascript (внутри объекта) :
toggle: function() {
var me = this;
var handler = function() { me.progress() };
me.intervalId = setInterval(handler, me.intervalTime);
//...More code
}
Я вроде как новичок в javascript, поэтому, насколько я могу судить, выполнение вышеуказанного фактически передает me
переменную в анонимную функцию. Я хотел посмотреть, есть ли более декларативный способ сделать это? Я хотел что-то вроде:
var handler = (function(o) { o.progress();})(this));
но, похоже, это не работает… Я что-то упускаю? Это тот случай, когда «так работает язык, поэтому просто объявите локальную переменную и разберитесь с ней»?
Обновить:
Источником моей проблемы было / остается мое неясное понимание области видимости и замыканий в javascript. Я нашел эту статью, которая поможет мне понять немного больше.
Комментарии:
1. Это не работает, потому что у вас их
)
слишком много. Возможно, неvar handler = (function(o) { o.progress();})(this);
работает?
Ответ №1:
Вы можете использовать «.bind()»:
var handler = function() { this.progress(); }.bind(this);
В новых браузерах есть «bind()», а в документах Mozilla есть надежная реализация, которую вы можете использовать для исправления старых браузеров.
Комментарии:
1. еще более краткое решение для моей ситуации
var handler = this.progress.bind(this)
. Спасибо за ваш вклад!
Ответ №2:
Причина
var handler = (function(o) { o.progress();})(this));
не работает, потому что она просто немедленно вызывает функцию anon, следовательно, немедленно вызывает o.progress()
и присваивает возвращаемое значение функции anon (неопределенное) handler
. Вам нужно вернуть фактическую функцию из внешней функции:
handler = (function(me){
return function(){
return me.progress();
}
}(this));
С другой стороны, это эквивалентно и выглядит так же плохо, как и присвоение переменной (но все равно может быть полезно, особенно если это нужно сделать в цикле, с изменением i, а не с исправлением this).
Кстати, если в функции progress нет никаких вызовов this
внутри нее, может быть достаточно простого выполнения handler = this.progress
(без скобок).
Ответ №3:
Анонимная функция имеет доступ к me
, поскольку она объявлена внутри внешней функции (the toggle
function); она закрыта внешней функцией.
Ваша handler
функция будет вызвана с помощью setInterval
, которая передает ровно ноль аргументов. Это означает, что вы не можете использовать параметры в самой функции-обработчике.
Если вы действительно хотите передать me
явно, вы могли бы написать функцию, принимающую параметр, и заставить эту функцию возвращать анонимную функцию без параметров, но которая могла бы получить доступ к параметру функции-создателя:
toggle: function() {
var me = this;
var handler = (function (o) { return function() { o.progress() }; })(me);
me.intervalId = setInterval(handler, me.intervalTime);
//...More code
}
Но это в основном добавляет слой перенаправления, на самом деле не делая его более разборчивым. Если вы не извлекаете эту создающую функцию извне:
function createProgressHandler(o) {
return function() {
o.progress();
};
}
// ...
toggle: function() {
var me = this;
var handler = createProgressHandler(me);
me.intervalId = setInterval(handler, me.intervalTime);
//...More code
}
Ответ №4:
То, что у вас есть, — это закрытие. Функция, которая создается и назначается handler
, сохраняет ссылку на me
объект. Это обычный JavaScript, и именно так обычно работают замыкания.
Комментарии:
1. Это не его проблема. Он жалуется, что
this
не может быть закрыт, что вынуждает егоvar me = this
.2. Я согласен, но то, что он хочет сделать, равносильно борьбе с языком. Я — и, вероятно, все остальные, кто пишет код JavaScript — хотели бы обойтись без назначения локальной переменной, но это то, что есть.
Ответ №5:
Вы пытались вернуть функцию подобным образом?
var handler = function(o){
return function(){
o.progress();
}
}(me);
Теперь вы можете вызвать:
handler();