2014-02-27 28 views
2

我使用顯露模塊模式的一些畫廊代碼:這等於窗口requestAnimationFrame回調

window.jdiGallery = (function() { //Structure from http://code.tutsplus.com/tutorials/build-your-first-javascript-library--net-26796 
var instance = null; 

function Gallery (nodeList, options) { 
    this.settings = this.extend({ 
     'transitionSpeed': 100, //in ms 
     'slideSpeed': 5000 
      }, options); 
     this.requestAnimationId; //We need this handle for canceling the RAF 
     this.start = null; //To help determine how far we are between transitions 
     for(var i = 0; i < nodeList.length; i++) 
      this.instances[i] = this.init(nodeList[i]); 
     } 


    Gallery.prototype.init = function(el){ 
     var slideEls = el.querySelectorAll('* > .nd-slide'); 
     var slides = []; 
      //this is equal to the Gallery instance 
     for(var i = 0; i < slideEls.length - 1; i++) 
      slides.push(new Slide(slideEls[i], i, this.settings["inTransition"], this.settings["outTransition"])); 
    }  
    Gallery.prototype.moveToNext = function(timestamp){ 
     var progress; 
     if (this.start === null) //this is equal to window 
      this.start = timestamp; 
     progress = timestamp - this.start; 

     if (progress > 5000) { 
      console.log('moving to next'); 
      this.start = null; 
      requestAnimationFrame(this.moveToNext); 
     } 
    } 

    return { 
     create: function (selector, options) { 
      //creation code omitted for brevity    
      instance = new Gallery(els, options); 

      this.requestId = window.requestAnimationFrame(instance.moveToNext); 
     }, 

create被調用,它最終調用Gallery.init()。在該函數中,this等於Gallery的實例。

然後我通過Gallery.moveToNext()作爲回調我的requestFrameAnimation。當我們進入moveToNext時,this的值是window。爲什麼它沒有像我期望的那樣引用Gallery

回答

3

是的,這是在JavaScript中一個常見的問題。在JavaScript中的this綁定取決於函數如何被稱爲

的一般規則是(對於瀏覽器):

  • 如果函數是從裸標識符調用,this設置爲window

    > var foo = function() { console.log(this); }; 
    > foo(); 
    Window 
    
  • 如果函數是從直接調用一個物體,this設置爲物體

    > var bar = { 
    >  bar: function() { console.log(this); } 
    > }; 
    > bar.foo(); 
    Object 
    
  • 如果一個函數被調用,要麼.call().apply()this被設置爲任何被傳遞在作爲第一個參數

在這種情況下,​​只具有對moveToNext函數本身,而不是在一個參考其上下文。一個解決方案是使用Function.prototype.bind

requestAnimationFrame(this.moveToNext.bind(this)); 

此外,您可以緩存裏面的Gallery.prototype.init

this.moveToNextBound = this.moveToNext.bind(this); 

你也可以使用匿名函數結合的版本,但這樣做,你將需要重新綁定this到另一個變量。

var self = this; 
requestAnimationFrame(function() { self.moveToNext.apply(arguments); }); 
+0

+1這個答案肯定比我的好 – slezica

1

this.moveToNext傳遞裸函數,沒有上下文。事實上,你從this採取它沒有區別。

使用this.moveToNext.bind(this)

+1

僅供參考,您可能需要從[這裏]的填充工具(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)舊版本瀏覽器,唐本身有'bind()'。 –