Ну сейчас вы наслушаетесь всяких фантазий:) На самом деле вы столкнулись с 3-мя вещами.
Объект активации
Это куда ссылается волшебное слово
this. Зависит от способа вызова функции (она же метод). Неразрывно связан с контекстом выполнения.
Контекст выполнения
Контекст выполнения отложенного кода в виде таймеров
setTimeout и
setInterval — глобальный. Поэтому при отложенном вызове
this ссылается на глобальный объект. Для клиентского JS глобальный объект —
window. А у
window нет такого свойства
isRun.
Как побороть
Установить явно объект вызова
activation object. Для этого есть 3 метода функций —
call,
apply,
bind. Например:
var timer = function (element, callback) {
...
}.bind(this);
После такой привязки функция timer будет выполняться с объектом активации, ссылающимся на тот контекст, где была создана.
Немедленно исполняемые функциональные выражения (IIFE)
По сути вопрос касается всё того же контекста выполнения.
Вызов функции немедленно после её объявления (или инициализации) выполняется не просто так. В этом случае объектом активации (это куда ссылается
this) является глобальный объект.
То есть получается, что даже если принять меры по указанию в timer нужного объекта активации, в функции inner объект активации всё равно будет глобальный объект.
Как побороть
Передать в замыкании для inner ссылку на нужный объект. Кстати, замыкание — это все внешние контексты для созданной функции (для конструктора Function, для таймеров и для
eval — отдельная песня). Для инструкции
with тоже отдельная песнь, хотя и
deprecated.
var timer = function (element, callback) {
var $this = this;
(function inner() {
console.log(slider.isRun); // Так свойство видно
console.log($this.isRun); // И так тоже
setTimeout(inner, 1000);
})();
}.bind(this);
Не создавать функцию inner (а по факту именованный функциональный литерал), и вызывать
timervar timer = function (element, callback) {
console.log(slider.isRun); // Так свойство видно
console.log(this.isRun); // И так тоже
setTimeout(timer, 1000);
}.bind(this);
Итог
Вот так можно представить ваш код
var slider = {
isRun: true,
run: function (element, callback) {
var timer = function (element, callback) {
var $this = this;
(function inner() {
console.log(slider.isRun); // Так свойство видно
console.log($this.isRun); // И так тоже
setTimeout(inner, 1000);
})();
}.bind(this);
setTimeout(function () {
timer(element, callback);
}, 1000);
}
}