2013-09-25 11 views
13

私はこのプロトタイプオブジェクトStageを持ち、この再帰呼び出し以外はすべての部分が機能します。 this.startを使用して、if文Stage.prototype.startが、この中で呼び出されるように、それをしようとしてプロトタイプ関数内の再帰呼び出し

Stage.prototype.start = function(key) { 
     //var maxScrollLeft = document.getElementById("content").scrollWidth; 
     $content.scrollLeft($content.scrollLeft() + this.initspeed); 
     if(key < this.maxScrollLeft || key > 0) { 
       setTimeout(function() { 
         this.start(key+2); 
       },1); 
     }else{ 
       console.log("stop"); 
     } 
} 

イム();しかし、私はいつも得ます Uncaught TypeError: Object [object global] has no method 'start' 私はそれが匿名関数の呼び出しと関係していると思います、どのように私はこれを修正することができますか?

答えて

20

this匿名コールバック内のsetTimeoutは、関数がどこにも束縛されていないためグローバルオブジェクトを指しているため、グローバルスコープに吊り上げられます。この場合、コールバックはwindow(ブラウザ)またはglobal(ノードなど)コンテキストから実行されます。そのため、thisは、そのコンテキストから関数が呼び出されるため、グローバルスコープを指します。この問題には多くの方法があります。 1つの簡単な方法は、thisを変数にキャッシュし、コールバック関数で使用することです。

Stage.prototype.start = function(key) { 
      var self = this; //cache this here 
      //var maxScrollLeft = document.getElementById("content").scrollWidth; 
      $content.scrollLeft($content.scrollLeft() + this.initspeed); 
      if(key < this.maxScrollLeft || key > 0) { 
        setTimeout(function() { 
          self.start(key+2); //use it to make the call 
        },1); 
      }else{ 
        console.log("stop"); 
      } 
    } 

Fiddle

あなたがすることができるもう一つの方法はfunction.prototype.bindを使用してコンテキストをバインドすることです。

Stage.prototype.start = function(key) { 
      //var maxScrollLeft = document.getElementById("content").scrollWidth; 
      $content.scrollLeft($content.scrollLeft() + this.initspeed); 
      if(key < this.maxScrollLeft || key > 0) { 
        setTimeout((function() { 
          this.start(key+2); //now you get this as your object of type stage 
        }).bind(this),1); //bind this here 
      }else{ 
        console.log("stop"); 
      } 
    } 

Fiddle

関連する問題