Как я могу заставить setTimeout выполнить метод в объекте? - PullRequest
2 голосов
/ 21 февраля 2010

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

Рассмотрим следующие методы в объекте: (я использую jQuery)

myObj = {};

myObj.message = "woot!";

myObj.bindEvents = function() {

        var that = this;

        $("#menuPanel")
            .bind("mouseleave", function() { 

                    that.timer = setTimeout(that.closeMenu,500); 

            });

    }

myObj.closeMenu = function() {

     // close the menu

     alert(this.message);

}

Это не работает. То есть this.message появляется неопределенным. После небольшой копки я понимаю почему. :) Ссылка 'that' недоступна для кода внутри setTimeout во время выполнения.

Мне интересно, как лучше всего обойти этот тип проблемы? Как я могу иметь метод, который использует setTimeout, вызывать другой метод в том же объекте, и все еще иметь доступ к свойствам в объекте?

Заранее спасибо за помощь.

1 Ответ

4 голосов
/ 21 февраля 2010

Проблема здесь в том, что вы отсоединяете метод closeMenu от его объекта. У вас возникла бы такая же проблема, если бы вы сделали это:

var closeMenu = myObj.closeMenu;  // detaching the method from the object
closeMenu();

Отключение и вызов таких методов означает, что они больше не применяются к объектам, на которых они были созданы. В вашем примере вы делаете почти то же самое:

// Setting the first parameter of setTimeout to be the detached closeMenu method
that.timer = setTimeout(that.closeMenu,500); 

Исправление для первого метода состояло бы в использовании call или apply методов:

var closeMenu = myObj.closeMenu;  // detaching the method from the object
closeMenu.apply(myObj);

Но это не сработает для таймера. Вместо этого создайте анонимную функцию:

that.timer = setTimeout(function () { that.closeMenu(); },500); 

<ч /> Также стоит упомянуть bind() - его не следует путать с $('#selector').bind() в jQuery - методом, который использовался в различных блогах и в некоторых библиотеках (Prototype является наиболее заметным) уже давно и, наконец, был реализован в ECMAScript edition 5 .

that.timer = setTimeout(that.closeMenu.bind(that),500);

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

...