2012-11-21 66 views
0

我正在嘗試創建一個函數擴展來消除任何函數(如果該函數在快速連續中被多次調用,只執行一次,並最優地返回一個緩存的值)。如何訪問擁有Function.prototype擴展的函數?

我打算在UI框架中使用它,但我希望它是可移植的。我到目前爲止的代碼如下:

Function.prototype.debounce = function() 
{ 
    var originalFunction = this; //this should be 'clickButton' in the example implementation 
    var originalArguments = arguments; 

    function debouncedFunction() 
    { 
     var originalContext = this; 
     return originalFunction.apply(originalContext,originalArguments) 
    } 

    if(this.__DEBOUNCEDVALUE === undefined) 
    { 
     this.__DEBOUNCEDVALUE = debouncedFunction(); 
     if(this.__DEBOUNCEDVALUE === undefined) 
      this.__DEBOUNCEDVALUE = null; 
     setTimeout(function(){originalFunction.__DEBOUNCEDVALUE = undefined},1000); 
    } 

    return this; 
} 

接下來,我定義了一個通用的功能,「clickButton」,它看起來像這樣:

function clickButton() 
{ 
    document.getElementById('log').innerHTML += "<br/>Clicked "+arguments[1]; 
    return "some value"; 
} 

當我打電話clickButton.debounce(3,4),它的工作原理。它每秒只記錄一次文檔,但每次調用時都會返回。

但是,當我通過監聽器(buttons[i].addEventListener('click',clickButton.debounce))調用它時,originalFunction變量設置爲按鈕,而不是該函數。不是一個大驚喜。在這個例子中,我如何從debounce中得到對clickButton的引用?

編輯: 我試過切換到使用defineProperty,它允許我在訪問時保存上下文和函數。不幸的是,這在所有情況下都不起作用(將它放入Sencha Touch中的tap處理程序會導致在Window範圍內調用一個函數)。這更接近,但仍然不可接受。

Object.defineProperty(Function.prototype,'debounce',{get: function() 
    { 
     var originalFunction = this; 
     var execute = function() 
     { 
      if(originalFunction.__DEBOUNCEDVALUE === undefined) 
      { 
       originalFunction.__DEBOUNCEDVALUE = originalFunction.apply(this,arguments); 
       if(originalFunction.__DEBOUNCEDVALUE === undefined) 
        originalFunction.__DEBOUNCEDVALUE = null; 
       setTimeout(function() 
        { 
         originalFunction.__DEBOUNCEDVALUE = undefined; 
         console.log("Reset"); 
        },5000); 
      } 
      else 
       console.log("Return cached value"); 

      return originalFunction.__DEBOUNCEDVALUE; 
     } 
     return execute; 

    }}); 

回答

2

這隻能通過某種方法將函數對象綁定到debounce

一種方法是使用.bind

buttons[i].addEventListener('click',clickButton.debounce.bind(clickButton)), 

另一種方式是通過封閉在clickButton匿名函數。

buttons[i].addEventListener('click',function(e) { 
    return clickButton.debounce.apply(clickButton, arguments); 

     // The following would suffice for this example: 
    // return clickButton.debounce(e); 
}), 

但除了這些各種各樣的技術,debounce將沒有從中傳遞給addEventListener,當它被引用的對象的內存。