3

次の jQuery コードがあるとします。

var FooBar = {
    zizzle: function (callback) {
        var x, y, z;
        // … do stuff with x y and z
        callback(z, y, z);
    }
}

$("a[href]").each(function () {
    var link = this;

    // do things with the link, e.g. 
    $(link).data('fiddle', "deedee")

    function do_something() {
        console.log("I would use the link variable here:", link)
        // lots of code here using link
        // blah, blah, blah link
    }

    $(this).click(function () {
        FooBar.zizzle(do_something);
    });
});

現在、が定義されているdo_something関数の内部にあるためlink、その変数にアクセスできます (クロージャ)。ただし、リンクごとに関数を作成することを避けることができるかどうかは疑問です。私はむしろこれに近いことをしたい:

var FooBar = {
    zizzle: function (callback) {
        var x, y, z;
        // … do stuff with x y and z
        callback(z, y, z);
    }
}

function do_something() {
    console.log("I would use the link variable here:", link)
    // lots of code here using link
    // blah, blah, blah link
}

$("a[href]").each(function () {
    var link = this;

    // do things with the link, e.g. 
    $(link).data('fiddle', "deedee")

    $(this).click(function () {
        FooBar.zizzle(do_something);
    });
});

したがって、それdo_somethingは一度だけ作成されます。ただし、これを行うとdo_something、 の値がなくなりますlink

この場合、 のコードを変更するFooBarことはできず、コールバックのみが必要であり、追加のパラメーターを送信できないと仮定します。

私が考えた唯一の代替案は、少なくとも必要に応じて関数のみを作成する、次のようなものです。

var FooBar = {
    zizzle: function (callback) {
        var x, y, z;
        // … do stuff with x y and z
        callback(z, y, z);
    }
}

function do_something_maker(link) {
    return function (x, y, z) {
        console.log("I would use the link variable here:", link)
        // lots of code here using link
        // blah, blah, blah link
    }
}

$("a[href]").each(function () {
    var link = this;

    // do things with the link, e.g. 
    $(link).data('fiddle', "deedee")

    $(this).click(function () {
        FooBar.zizzle(do_something_maker(link));
    });
});

それが最善の選択肢ですか?

4

5 に答える 5

2

どうぞ:

var FooBar = {
    zizzle: function (callback) {
        var x, y, z;
        // … do stuff with x y and z
        callback(z, y, z);
    }
}

function do_something() {
    console.log("I would use the link variable here:", do_something.link);
    //if no link exists, abort
    if(!do_something.link){return;}
    //code with do_something.link


    //you might want to delete afterwards
    //delete do_something.link;
}

$("a[href]").click(function () {
    do_something.link = this;
    FooBar.zizzle(do_something);
});

非同期で処理が遅い場合は、do_something_maker や bind/$.proxy アプローチのように遅延させることができますが、リンクごとに 1 回だけ (最初のクリックで $.data に追加します)。

var FooBar = {
    zizzle: function (callback) {
        var x, y, z;
        // … do stuff with x y and z
        callback(z, y, z);
    }
}

function do_something() {
    console.log("I would use the link variable here:", this);

}

$("a[href]").click(function () {
    var fn = $.data(this, 'zizzleCB') || $.data(this, 'zizzleCB', do_something.bind(this));
    FooBar.zizzle(fn);
});
于 2013-11-12T21:15:20.450 に答える
0

興味のある要素のコンテナをクリックして登録する必要があります。あなたの場合、それはdocument.bodyになります。次に、いつアクションを実行するかを判断する追加のセレクターを用意します: http://api.jquery.com/on/以下に例を示します。

function create_do_something($link){
  return function(z,y,x){
    do_something(z,y,x);
  };
}
$(document.body).on("click","a[href]",function () {
  var $link =  this;
  FooBar.zizzle(create_do_something($link));
});

$("a[href]").clickまたは$("a[href]").onjQueryを使用して解決策がある場合、セレクターで見つかったすべての要素に対してクロージャーが作成されます。

Chrome でいくつかのテストを実行し、ヒープ スナップショットを実行すると、次の結果が得られます。

jQuery も JS コードもありません:

2557回の閉鎖

コードはまったくありません (jQuery と jQuery ui のみ):

5832回の閉鎖

次のコードで

$(document.body).on("click","div"
  ,function(){console.log("hi");});

5834 個のクロージャ (2 div を含む)

5834 個のクロージャ (100 div を含む)、クロージャの量は同じままであることに注意してください

次のコードで

$("div").click(function(){console.log("hi");});

5835 個のクロージャ (2 div を含む)

5933 個のクロージャー (100 個の div を含む)。さらに 98 個のクロージャーがあることに注意してください。jQuery は、セレクターで見つかったすべての要素にクロージャーを追加します。

では、なぜ$("div").clickより多くの閉鎖があるのでしょうか?

jQuery 1.10.2 は 4762 行目で圧縮されていません:

 eventHandle = elemData.handle = function( e ) {

そこにブレークポイントを設定すると、セレクターで見つかった各要素に対して jQuery がクロージャーを追加することがわかります。したがって、$("div") は 100 を返しましたが、$(document.body) は div の数に関係なく 1 を持っています。

于 2013-11-13T04:53:40.240 に答える
0

キックのために:

var Util = function() {};
Util.prototype.do_something = function() {};

var FooBar = function() {
};
FooBar.prototype.zizzle = function(fn) {};

var fooBar = new FooBar();
var util = new Util();
fooBar.zizzle(util.do_something);

これはあなたに何を与えましたか?

作成するオブジェクトごとに、FooBarインスタンスが 1 つ少なくなりますzizzle(すべての関数は実質的に 1 つ少ないオブジェクトであるため)。のインスタンスごとにUtil、 のインスタンスが 1 つ少なくなり、インスタンスdo_something が必要な時期をより適切に決定できるようになりUtil、使用されていない関数でグローバル オブジェクトが乱雑になることはありません。

これが機能するのは、関数をオブジェクト リテラルで横行させたり{}、グローバル名前空間にアタッチしたりするのではなく、プロトタイプで 1 つの関数を定義しているためです。

于 2013-11-12T21:23:53.700 に答える
0

Function.prototype.bind を使用できます。

var FooBar = {
    zizzle: function (callback) {
        var x, y, z;
        // … do stuff with x y and z
        callback(z, y, z);
    }
}

function do_something() {
    console.log("'this' refers to link here", this)
    // lots of code here using link
    // blah, blah, blah link
}

$("a[href]").each(function () {
    link = this;
    $(this).click(function () {
        FooBar.zizzle(do_something.bind(link));
    });
});
于 2013-11-12T21:25:53.233 に答える
0

"link" を引数として zizzle 関数に渡して、それを callback に渡さないのはなぜですか?

次のように:

var FooBar = {
    zizzle: function (callback,link) {
        var x, y, z;
        // … do stuff with x y and z
        callback(x, y, z, link);
    }
}

function do_something(x, y, z, link) {
    console.log("I would use the link variable here:", link)
    // lots of code here using link
    // blah, blah, blah link
}

$("a[href]").on("click", function () {
    FooBar.zizzle(do_something, this);
});
于 2013-11-12T21:08:23.267 に答える