我正在尝试做一个shakeEffect,但是我收到了这个错误:
Uncaught TypeError: Cannot read property '1' of undefined
setTimeout.elementsCollection.style.position shake.js:66
第66行是:
this.elementsCollection[ i ].style.left = parseInt( Math.random() * 20 ) + 'px';
完整的代码:
Shake.prototype.shakeEffect = function(){
if( this.elementsCollection.length != false ){
var positions = this.shakePosition.split( '|' );
for( var i = 0; i < this.elementsCollection.length; ++i ){
this.elementsCollection[ i ].style.position = 'relative';
this.effectInterval = setInterval( function( elementsCollection ) {
for( var x = 0; x < positions.length; ++x ){
switch( positions[ x ] ){
case 'left':
this.elementsCollection[ i ].style.left = -Math.abs( Math.random() * 20 ) + 'px';
break;
case 'right':
this.elementsCollection[ i ].style.left = parseInt( Math.random() * 20 ) + 'px';
break;
case 'top':
case 'up':
this.elementsCollection[ i ].style.top = -Math.abs( Math.random() * 20 ) + 'px';
break;
case 'down':
this.elementsCollection[ i ].style.top = parseInt( Math.random() * 20 ) + 'px';
break;
}
}
} , this.getInterval() );
setTimeout( function(){
return function(){
clearInterval( this.effectInterval );
this.elementsCollection[ i ].style.position = null;
}
} , this.getTimeout() );
}
}
}
谢谢!
答案 0 :(得分:1)
有些事情,你不能在setInterval中的函数中发送参数。你必须这样做:
setInterval(function (elementsCollection) { alert(elementsCollection) }, 1000 /*delay*/, array)
所以这应该有效:
this.effectInterval = setInterval( function( elementsCollection ) {
for( var x = 0; x < positions.length; ++x ){
switch( positions[ x ] ){
case 'left':
elementsCollection[ i ].style.left = -Math.abs( Math.random() * 20 ) + 'px';
break;
case 'right':
elementsCollection[ i ].style.left = parseInt( Math.random() * 20 ) + 'px';
break;
case 'top':
case 'up':
elementsCollection[ i ].style.top = -Math.abs( Math.random() * 20 ) + 'px';
break;
case 'down':
elementsCollection[ i ].style.top = parseInt( Math.random() * 20 ) + 'px';
break;
}
}
} , this.getInterval(), this.elementsCollection );
setTimeout( function(elementsCollection){
return function(){
clearInterval( this.effectInterval );
elementsCollection[ i ].style.position = null;
}
} , this.getTimeout(), this.elementsCollection );
答案 1 :(得分:0)
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
具有循环限制值。
将变量传递给setTimeout / setInterval的cabback functin的正确方法如下:
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() );