Вызов пользовательских методов вызова с помощью setTimeout теряет область действия
У меня возникла проблема с созданием объекта Javascript и вызовом методов внутри этого объекта с помощью setTimeout. Я пробовал различные обходные пути, но всегда во второй части моего цикла область становится объектом окна, а не моим пользовательским объектом. Предупреждение: я довольно новичок в javascript.
мой код:
$(function() {
slide1 = Object.create(slideItem);
slide1.setDivs($('#SpotSlideArea'));
slide1.loc = 'getSpot';
slide2 = Object.create(slideItem);
slide2.setDivs($('#ProgSlideArea'));
slide2.loc = 'getProg';
slide2.slide = 1;
setTimeout('triggerSlide(slide1)', slide1.wait);
setTimeout('triggerSlide(slide2)', slide2.wait);
});
function triggerSlide(slideObject) {
slideObject.changeSlide(slideObject);
}
var slideItem = {
div1: null,
div2: null,
slide: 0,
wait: 15000,
time: 1500,
loc: null,
changeSlide: function(self) {
this.slide ? curDiv = this.div1:curDiv = this.div2;
$(curDiv).load(location.pathname + "/" + this.loc, this.slideGo(self));
},
setDivs: function(div) {
var subDivs = $(div).children();
this.div1 = subDivs[0];
this.div2 = subDivs[1];
},
slideGo: function(self) {
if(this.slide) {
$(this.div2).animate({
marginLeft: "-300px"
}, this.time);
$(this.div1).animate({
marginLeft: "0"
}, this.time);
setTimeout('triggerSlide(self)', this.wait);
} else {
$(this.div1).animate({
marginLeft: "300px"
}, this.time);
$(this.div2).animate({
marginLeft: "0"
}, this.time);
setTimeout('triggerSlide(self)', this.wait);
}
this.slide ? this.slide=0:this.slide=1;
}
}
Моя последняя попытка заключалась в создании вспомогательной функции triggerSlide, чтобы я мог попытаться передать ссылку на объект с помощью моих методов, но даже это не работает.
Я мог бы использовать setInterval, но он работает, однако:
- Я хочу, чтобы анимация завершилась до перезапуска таймера
- Я не узнаю, как обойти эту проблему.:)
Ответы
Ответ 1
Это должно быть обязательно прочитано для программистов Javascript, начатых с языка (и с помощью Stackoverflow).
В отличие от Java, нет никакого "связывания" функций с любым объектом, независимо от того, как они объявлены. Связывание контекста объекта происходит только во время вызова функции. Таким образом, когда вы передаете ссылку на функцию на что-то вроде "setTimeout", не имеет значения, что вы получили функцию от какого-либо объекта. Это просто функция, и "setTimeout" вызовет ее со стандартным контекстом — объект window
.
Есть много способов справиться с этим (и я не буду называть это "проблемой", это факт языка и очень мощный). Если бы вы использовали какую-то фреймворк, было бы проще.
Другое дело: вы привязываете свой тайм-аут и обработчики интервалов как строки, содержащие код. Это довольно уродливая практика, поэтому вы должны привыкнуть к формированию выражений функций — то есть выражения, значения которых являются функциями.
Для вашего обработчика "slideItem", например, вы можете сделать это:
// ...
setTimeout(function() { slideItem.changeSlide(); }, 5000);
Таким образом, функция, вызванная механизмом тайм-аута, всегда вызывает "changeSlide" с вашим объектом "slideItem" в качестве контекста. Вам не нужен этот параметр "self" в "changeSlide", потому что "this" укажет на правильный объект.
[править] Я отмечаю, что вы действительно используете jQuery, что хорошо.
Ответ 2
Я не могу проверить этот код прямо сейчас, но помогает ли это?
setTimeout(function(){triggerSlide(slide1)}, slide1.wait);
Ответ 3
Это jQuery, правильно? Там параметр обратного вызова animate()
; передайте ему функцию, которую вы хотите вызвать после завершения анимации, и jQuery позаботится о ее вызове. Обратный вызов должен захватить область, которую вы хотите просто отлично.