如何访问拥有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;
}});

这只能通过将函数对象绑定到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时将没有引用对象的内存。

最新更新