web-dev-qa-db-ja.com

jQuery.each()を使用する必要がありますか?

私はオブジェクトの配列に対して非常に頻繁に反復を行っており、jQuery.each()を使用しています。ただし、速度とメモリの問題があり、プロファイラーによると最も呼び出されるメソッドの1つはjQuery.each()です。そのパフォーマンスについての路上での言葉は何ですか?単純なforループに切り替える必要がありますか?もちろん、私も自分のコードの多くの問題を修正しています。

34
pr1001

JQueryのそれぞれのソースコードは次のとおりです(JohnResigとMIT License)に感謝します):

each: function( object, callback, args ) {
    var name, i = 0, length = object.length;

    if ( args ) {
        if ( length === undefined ) {
            for ( name in object )
                if ( callback.apply( object[ name ], args ) === false )
                    break;
        } else
            for ( ; i < length; )
                if ( callback.apply( object[ i++ ], args ) === false )
                    break;

    // A special, fast, case for the most common use of each
    } else {
        if ( length === undefined ) {
            for ( name in object )
                if ( callback.call( object[ name ], name, object[ name ] ) === false )
                    break;
        } else
            for ( var value = object[0];
                i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
    }

    return object;
}

トレースして確認できるように、ほとんどの場合、基本的なforループを使用しており、オーバーヘッドは実際にはコールバック自体だけです。パフォーマンスに違いはありません。

編集:これは、セレクターのオーバーヘッドがすでに発生しており、入力された配列objectが与えられていることに気付いたためです。

15
Justin Swartsel

この記事 (#3)いくつかのパフォーマンステストを実行し、jQuery.each関数がネイティブのjavascriptforループの約10倍遅いことを発見しました。

From jQueryのパフォーマンスを即座に向上させる10の方法-3。それぞれの代わりにForを使用
Firebug を使用すると、2つの関数のそれぞれの実行にかかる時間を測定できます。

var array = new Array ();
for (var i=0; i<10000; i++) {
    array[i] = 0;
}

console.time('native');
var l = array.length;
for (var i=0;i<l; i++) {
    array[i] = i;
}
console.timeEnd('native');

console.time('jquery');
$.each (array, function (i) {
    array[i] = i;
});
console.timeEnd('jquery');

上記の結果は、ネイティブコードの場合は2ミリ秒、jQueryの「各」メソッドの場合は26ミリ秒です。ローカルマシンでテストし、実際には何も実行していない場合(単なる配列の入力操作)、jQueryの各関数はJSネイティブの「for」ループの10倍以上の時間がかかります。これは、CSS属性の設定やその他のDOM操作操作など、より複雑なものを扱うときに確実に増加します。

27
Jace Rhea

この方法により、速度が劇的に向上します。

var elements = $('.myLinks').get(), element = null;
for (var i = 0, length = elements.length; i < length; i++) {
    element = elements[i];
    element.title = "My New Title!";
    element.style.color = "red";
}

キャッシングによってパフォーマンスも向上します。

function MyLinkCache() {
    var internalCache = $('.myLinks').get();

    this.getCache = function() {
        return internalCache;  
    }

    this.rebuild = function() {
        internalCache = $('.myLinks').get();
    }
}

使用中で:

var myLinks = new MyLinkCache();

function addMyLink() {
    // Add a new link.
    myLinks.rebuild();
}

function processMyLinks() {
    var elements = myLinks.getCache(), element = null;
    for (var i = 0, length = elements.length; i < length; i++) {
        element = elements[i];
        element.title = "My New Title!";
        element.style.color = "red";
    }
}
7
ChaosPandion

ネイティブ機能の使用は、通常、JQuery.each()メソッドなどの抽象化よりも高速になります。ただし、JQuery.each()メソッドは簡単使用するので、コーディングが少なくて済みます。

正直なところ、文脈がなければ、どちらも正しい選択でも間違った選択でもありません。私は、それが良い/読みやすい/クリーンなコードであると仮定して、最初に簡単なコードを書くべきだという意見です。あなたが説明しているような状況に陥った場合、それはあなたのボトルネックがどこにあるかを見つけてより速いコードを書く時よりも、顕著な遅れがあります。

これらのシナリオでJQuery.each()メソッドを置き換えるmightヘルプ。ただし、コードを見ていないと、JQueryメソッドに関係のないボトルネックが発生している可能性があります。

6
MillsJROSS

Jqueryを最大限に活用するための1つの方法は、何かを取得する必要があるたびにDOMを再トラバースするのではなく、返された結果の配列を変数に格納することです。

してはいけないことの例:

$('.myLinks').each(function(){
    // your code here
});
$('.myLinks').each(function(){
    // some more code here
});

より良い練習:

var myLinks = $('.myLinks');
myLinks.each(function(){
    // your code here
});
myLinks.each(function(){
    // some more code here
});
6
a432511