Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   таки опять вопрос про this (https://javascript.ru/forum/misc/30916-taki-opyat-vopros-pro.html)

LittlePony 20.08.2012 14:56

таки опять вопрос про this
 
Пытаюсь понять эту тему, потому пишу обыкновенный jquery-слайдер, но чтобы в объекте был.
Вот какая ерунда выходит:
PromoBlock = {
	options: {
		animateDuration: 800,
		animateEasing: 'swing',
		autoslideDelay: 2000
	},
	SwitchTo: function(index){
		var options = this.options
		…
	},
	AutoSlide: function(){
		var Switch2Next = this.SwitchTo
		var autoslideTimer = setInterval(Switch2Next,this.options.autoslideDelay)
	},
	Init: function(){
		…
		this.AutoSlide()
	}
}
PromoBlock.Init()

Из этого кода вырезано всё несущественное для вопроса.
Функция SwitchTo вызывается либо сама по себе, либо через setInterval, который, как известно, меняет контекст.
Соответственно, когда вызывается через setInterval, внутри неё var options = this.options не срабатывает, поскольку this == window.
Вот только я не понимаю, как правильно поступить, чтобы и в этом случае this был объект PromoBlock.

vadim5june 20.08.2012 15:07

так попробуйте
var t=this;
var autoslideTimer = setInterval(Switch2Next,t.options.autoslideDelay)

LittlePony 20.08.2012 15:18

vadim5june, спасибо. Но именно длительность интервала совершенно нормально передаётся и так. Ошибка именно внутри функции SwitchTo. Именно внутри неё this указывает на объект PromoBlock, если функция вызывается сама по себе, и на window, если функция вызвана через setInterval.
Природа этого явления понятна: setInterval — метод глобального объекта window, и соответственно, он задаёт контекст выполнения функции.
Непонятно, как вызвать эту функцию через setInterval, чтобы её контекст был объект PromoBlock

kobezzza 20.08.2012 15:24

Вы можете использовать вызовы call/apply, для явного указания this функции, а также можете явно привязать один контекст к функции, с помощью метода bind (для древних браузеров придётся реализовать самому).

Информацию о всех этих методах найти в инете не проблема.

vadim5june 20.08.2012 15:26

а если так
var t=this;
var autoslideTimer = setInterval(function(){Switch2Next.call(t)},this.options.autoslideDelay)

LittlePony 20.08.2012 15:47

про call/apply была первая мысль, но с ходу не получилось, первая попытка была именно такой: var autoslideTimer = setInterval(function(){Switch2Next.call(t)},this.o ptions.autoslideDelay). Это не сработало.
Вот такой вариант работает исправно:
var t = this
		var Switch2Next = function(){ t.SwitchTo.call(t) }
		var autoslideDelay = t.options.autoslideDelay
		var autoslideTimer = setInterval(Switch2Next,autoslideDelay)

При этом даже строка var autoslideDelay = t.options.autoslideDelay не обязательна, она присутствует только для большей наглядности.
Всё ли правильно я делаю? Не покидает ощущение, что что-то не так, хотя работает в браузерах всё исправно.

nerv_ 20.08.2012 15:50

LittlePony, мы же тебе уже сказали и даже показали :)

vadim5june 20.08.2012 15:56

это промежуточное Switch2Next не нужно
по идее вот так должен работать
var t=this;
var autoslideTimer = setInterval(function(){t.SwitchTo()},this.options.autoslideDelay)

LittlePony 20.08.2012 16:06

Цитата:

Сообщение от vadim5june (Сообщение 199056)
это промежуточное Switch2Next не нужно
по идее вот так должен работать
var t=this;
var autoslideTimer = setInterval(function(){t.SwitchTo()},this.options.autoslideDelay)

Да, работает. И кажется я даже начинаю понимать, почему это работает, мой вариант выше работает, а первый вариант не работал. Большое спасибо!
Скажите, правильно ли я теперь понимаю?
Вариант:
var t=this;
var autoslideTimer = setInterval(function(){t.SwitchTo()},this.options.autoslideDelay)

Здесь в переменной t уже вполне определённый объект, который до применения setInterval был определён как this, который в тот момент однозначно указывал на сам объект PromoBlock(и будет на него указывать, как его ни обозвать), у этого объекта есть метод SwitchTo, который и вызывается в контексте объекта, который из t уже никуда не денется, как бы setInterval ни менял контекст.

Вариант же мой рабочий — это почти то же самое, но расписанное большим количеством шагов.

vadim5june 20.08.2012 16:08

Цитата:

Сообщение от LittlePony
Здесь в переменной t уже вполне определённый объект, который до применения setInterval был определён как this, который в тот момент однозначно указывал на сам объект PromoBlock(и будет на него указывать, как его ни обозвать), у этого объекта есть метод SwitchTo, который и вызывается в контексте объекта, который из t уже никуда не денется, как бы setInterval ни менял контекст

да правильно вызываем метод объекта PromoBlock


Часовой пояс GMT +3, время: 21:51.