関数拡張を作成して、任意の関数をデバウンスしようとしています(関数が連続して複数回呼び出された場合は、1回だけ実行し、キャッシュされた値を最適に返します)。
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)
、それは働きます。1秒に1回だけドキュメントにログを記録しますが、呼び出されるたびに戻ります。
ただし、リスナー(buttons[i].addEventListener('click',clickButton.debounce)
)を介して呼び出すと、originalFunction
変数は関数ではなくボタンに設定されます。大きな驚きではありません。clickButton
この例では、デバウンス内から参照を取得するにはどうすればよいですか?
編集:definePropertyの使用に切り替えてみました。これにより、アクセス時にコンテキストと関数を保存できます。残念ながら、これはすべての場合に機能するわけではありません(Sencha Touchのタップハンドラーに入れると、ウィンドウスコープ内で関数が呼び出されます)。これはより近いですが、それでも受け入れられません。
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;
}});