0

関数拡張を作成して、任意の関数をデバウンスしようとしています(関数が連続して複数回呼び出された場合は、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;

    }});
4

1 に答える 1

2

これは、関数オブジェクトをにバインドする何らかのメソッドを介してのみ実行できますdebounce

1つの方法は.bind

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

もう1つの方法は、を閉じる匿名関数を渡すこと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

于 2012-11-21T18:34:48.937 に答える