0

これは少し抽象的なかもしれませんが、JavaScriptクロージャなどに頭を悩ませようとしています。次のコードを使用してください。

function MyObj() {
    var me = this;

    this.foo = function(bar) {
        // Do something with 'bar'
    }

    // Set up lots of local variables etc.
    // ....

    $(window).load(function() {
        // Add a delegated click handler to specific <input> elements
        $(document).on('click.myobj', 'input.special', function() {
            // Do something with the <input> that triggered the click event
            me.foo(this);
        });
    });
}

var myObj = new MyObj();

クリックイベントにバインドされて渡された無名関数は、を参照するクロージャを作成しますme。私が知りたいのは、代わりにこのようなことをする方が良いかどうかです(閉鎖を避けるため):

$(window).load(function() {
    // Add a delegated click handler to specific <input> elements
    (function(localMe) {
        $(document).on('click.myobj', 'input.special', function() {
            // Do something with the <input> that triggered the click event
            localMe.foo(this);
        });
    })(me);
});

これはより良いアプローチですか、それとも私はクロージャーを作成することについて過度に妄想していますか?あるいは、「第三の道」はありますか?


編集

さらに、次のようなことを行う方がよいでしょうか。

$(window).load(function() {
    // Add a delegated click handler to specific <input> elements
    $(document).on('click.myobj', 'input.special', {localMe : me}, function(event) {
        // Do something with the <input> that triggered the click event
        event.data.localMe.foo(this);
    });
});
4

4 に答える 4

1

現在、匿名関数はjavascriptで大量に使用されています(引数として、およびスコープ/クロージャの即時関数として)。パフォーマンスの問題はありません。

しかし、おそらくコードの読み取りに問題がある可能性があります。変数が表示されたら、変数の出所を確認する必要があるためです。しかし、ここでは大したことはありません。

そして、2番目の例では、まだクロージャの「ブレーク」があります。の無名関数では、変数clickを使用するためです。localMeそして、それlocalMeはあなたの機能の外にある機能の議論です。

// Here, 'me' is a direct local variable.
$(window).load(function() {
    // Here, we are in an anonymous fonction, so 'me' is not a direct variable anymore. But you still can access it.

    // Add a delegated click handler to specific <input> elements
    (function(localMe) {
        // Here, 'localMe' is a direct local variable.
        $(document).on('click.myobj', 'input.special', function() {
            // We are in an anonymous function, so 'localMe' is not a direct variable anymore.

            // Do something with the <input> that triggered the click event
            localMe.foo(this);
        });
    })(me);
});

クロージャの「ブレーク」を本当に避けたい場合は、関数をオブジェクトにバインドする必要があります。ただし、すべてのブラウザbindが関数のメソッドをサポートしているわけではないことに注意してください。

于 2012-12-05T11:58:21.663 に答える
1

後者は(AFAIK)より効率的ですが、タイトなループで使用されない限り、おそらく測定可能ではありません。

その理由は、すべての変数の間接参照はスコープチェーンに従う必要があるためです。後者の場合、変数localMeは無名関数のパラメーターリストにあります。

前者の場合、変数はそこにはありませんが、外部スコープにあります。スコープチェーンを上るこのトラバーサルには、余分な時間がかかります。

于 2012-12-05T12:04:25.630 に答える
1

コンストラクターからイベントをバインドする場合は、常にクロージャを作成します。実際、インスタンスへの参照を保持するためにクロージャーも必要です。ただし、次のようなことを行う場合があります。

function MyObj() {
    this.foo = function(bar) {
        // Do something with 'bar'
    }

    // Set up lots of local variables etc.
    // ....
}

var myObj = new MyObj();
$(function() {
    $(document).on('click.myobj', 'input.special', function() {
        myObj.foo(this);
    });
});

コンストラクターのシングルトンインスタンスのみを作成する場合は、とにかく問題にはなりません。

于 2012-12-05T14:49:15.710 に答える
0

私はおそらくこのようにします:

var bind = function( fn, me ) { return function() { return fn.apply(me, arguments); }; },
    Object = (function() {
        function Object() {
            this.handler = bind(this.handler, this);
            // Add a delegated click handler to specific <input> elements.
            $(document).on("click.myobj", "input.special", this.handler);
        }

        Object.prototype.foo = function( bar ) {
            // Do something with "bar".
        };

        Object.prototype.handler = function( event ) {
            // Do something with the <input> that triggered the click even.
            return this.foo(event.currentTarget);
        };

        return Object;
    })();

var obj = new Object();

これにより、クロージャとiifeの使用がスキップされ、代わりに.applyが使用されます。それがより効率的かどうかはわかりませんが、それは別のオプションです。

于 2012-12-05T12:16:24.737 に答える