12

私はJavascriptで読んだ:良い部分...

JavaScriptの配列は実際にはオブジェクトであるため、for inステートメントを使用して配列のすべてのプロパティを反復処理できます。残念ながら、inはプロパティの順序について保証しません...

「各」関数がに基づいていることを私が知っている限り、 JQueryおよびアンダースコアライブラリからの関数for ineach、配列を反復処理するときに順序を保証しますか?迷惑な基準を避けようとしていforます。

前もって感謝します。

4

2 に答える 2

17

配列を反復処理する場合、順序は常に保証されます。(非配列の)オブジェクトを反復処理するときは、保証がないときです。ちなみに、配列はまだオブジェクトです。


eachfor inオブジェクト用、およびfor配列のようなものにすぎません。フレームワークはジョブの正しいループを決定し、同じロジックが適用されます。配列の反復は順序付けられますが、オブジェクトの反復は順序付けられません。

アンダースコアのソース:

var each = _.each = _.forEach = function (obj, iterator, context) {
        if (obj == null) return;
        if (nativeForEach && obj.forEach === nativeForEach) {
            obj.forEach(iterator, context);
        } else if (obj.length === +obj.length) {
            for (var i = 0, l = obj.length; i < l; i++) {
                if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
            }
        } else {
            for (var key in obj) {
                if (_.has(obj, key)) {
                    if (iterator.call(context, obj[key], key, obj) === breaker) return;
                }
            }
        }
    };

jQueryのソース:

each: function (object, callback, args) {
    var name, i = 0,
        length = object.length,
        isObj = length === undefined || jQuery.isFunction(object);
    if (args) {
        if (isObj) {
            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 (isObj) {
            for (name in object) {
                if (callback.call(object[name], name, object[name]) === false) {
                    break;
                }
            }
        } else {
            for (; i < length;) {
                if (callback.call(object[i], i, object[i++]) === false) {
                    break;
                }
            }
        }
    }
    return object;
}
于 2012-05-24T15:05:58.427 に答える
3

配列をループする方法は 2 つあります。配列のインデックス付き要素に対する数値ループ、または配列のオブジェクト プロパティfor inに対するループです。

var a = ['a','b'];
a[3] = 'e';
a[2] = 'd';
a.foo = function() { };
for(key in a)
    console.log(key);

プロパティが定義された順序であるため、これは を返します0 1 3 2 foo(ただし、ブラウザがその動作を示す必要さえあるという保証はありません)。

これまでのところ、数値ループの方が優れているように見えますが、予備の配列、つまりギャップのある配列を処理することはできません。ES5Array.forEachは指定されていない値を省略しますが、jQueryはプロパティ$.eachに基づいて数値ループを使用しlengthます。

var a = [1,2];
a[1000000] = 4;
a[9000] = 3;
a.foo = function() {};

// outputs 0, 1, 9000, 1000000 -- note they are in order
a.forEach(function(elem, index){ console.log(index); })

// outputs 0, 1, 9000, 1000000 -- same as above
_.each(a, function(elem, index){ console.log(index); }) 

// outputs a million values and locks up  your browser for a while
$.each(a, function(index){ console.log(index); })

したがって、両方ともインデックス順に値forEach$.each返しますがforEach、アンダースコアは、値が割り当てられていないインデックスを無視するため、スパース配列に対して優れているようです。

于 2012-05-24T15:51:20.340 に答える