【问题标题】:setInterval and prototype errorsetInterval 和原型错误
【发布时间】:2011-08-06 14:12:57
【问题描述】:

我正在尝试做一个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() );
              }
       }
}

谢谢!

【问题讨论】:

    标签: javascript this setinterval prototype-programming


    【解决方案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 );
    

    【讨论】:

    • + thx,我不知道您可以通过这种方式将参数发送到 setTimeout/setInterval 回调。不错:)
    • 其实对象有elementCollection是的,如果我没有就算他们会进入
    【解决方案2】:

    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 函数的正确方法是:

    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() );
    

    【讨论】:

    • 错误继续,但现在是:Uncaught TypeError: Cannot read property '1' of undefined self shake.js:66 Line 66: this.elementsCollection[ i ].style.left = parseInt( Math .random() * 20 ) + 'px';
    猜你喜欢
    • 2018-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多