обратный вызов setTimeout / setInterval выполняется в ином контексте, чем ваш объект, и когда он выполняется, ключевое слово this
не ссылается на ваш объект.
Создайте переменную, которая ссылается на экземпляр, и используйте ее вместоthis
в обратном вызове:
// ... code
var self = this;
setTimeout( function(){
return function(){
clearInterval( self.effectInterval );
self.elementsCollection[ i ].style.position = null;
}
} , this.getTimeout() );
// ... code
Когда выполняется обратный вызов this.effectInterval
, значение i
всегда является последним значением цикла.
Попробуйте сами:
for(var i=0;i<10;i++)
setTimeout(function(){console.log(i);},10);
Результат не такой, как ожидалось, поскольку функция выполняется после завершения цикла, а переменная i
имеет значение предела цикла.
Правильный способ передачи переменных в функцию cabback для setTimeout/ setInterval выглядит примерно так:
function mySetTimeout(args,callback,time){
return setTimeout(function(){
callback.apply({},args);
},time);
};
, а затем вы можете использовать его следующим образом:
for(var i=0;i<10;i++)
mySetTimeout([i],function(i){console.log(i);},10);
Итак, если вы используете специальную функцию mySetTimeout
и, конечно, аналогичныеmySetInterval
, ваш проблемный код можно переписать следующим образом:
this.effectInterval = mySetInterval([i] function( i ) {
for( var x = 0; x < positions.length; ++x ){
switch( positions[ x ] ){
case 'left':
self.elementsCollection[ i ].style.left = -Math.abs( Math.random() * 20 ) + 'px';
break;
case 'right':
self.elementsCollection[ i ].style.left = parseInt( Math.random() * 20 ) + 'px';
break;
case 'top':
case 'up':
self.elementsCollection[ i ].style.top = -Math.abs( Math.random() * 20 ) + 'px';
break;
case 'down':
self.elementsCollection[ i ].style.top = parseInt( Math.random() * 20 ) + 'px';
break;
}
}
} , this.getInterval() );