Last Updated: February 25, 2016
·
94.41K
· tsantef

Using _.each cleans up your javascript loops

Native for:

for (var i = 0; i < posts.length; i++) {
    var post = posts[i];
    for (var j = 0; j < post.comments.length; j++) {
        var comment = comments[j];
        console.log(comment.body);
    }
};

Native forEach (Modern Browsers)

posts.forEach(function(post) {
    post.comments.forEach(function(comment) {
        console.log(comment.body);
    });
});

http://underscorejs.org/#each

Underscore each (Cross-Browser):

_.each(posts, function(post) {
    _.each(post.comments, function(comment){
        console.log(comment.body);
    });
});

** Suger each (Cross-Browser) **

http://sugarjs.com/api/Array/each

posts.each(function(post) {
    post.comments.each(function(comment){
        console.log(comment.body);
    });
});

I know the native for loops are more efficient but for me clean readable code takes precedence.

[Edit] Additionally there is the ECMAScript 5's native forEach method which _.each delegates to but it's not supported by IE8. I'm a huge fan of the underscore.js library so I still prefer using the cross-browser _.each method.

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach

If you want to avoid using underscore.js you can conditionally patch older browsers to support forEach with the following (taken from the link above):

if ( !Array.prototype.forEach ) {
    Array.prototype.forEach = function(fn, scope) {
        for(var i = 0, len = this.length; i < len; ++i) {
            fn.call(scope || this, this[i], i, this);
        }
    }
}

6 Responses
Add your response

Good read. But everyone should be aware, extending Array's prototype chain breaks the way Javascript enumerates over Arrays with for loops.

over 1 year ago ·

I wouldn't recommend this.

Firstly, you need to load a 3rd party script to get the _.each() method.</p>

Secondly, that's not the proper way to extend native objects. It's not future proof. You should check for existence of each and if not found use Object.defineProperty to define a new property,</p>

Thirdly, there is no mention of the native forEach method. Underscore actually delegates to that if it exists.</p>

over 1 year ago ·

I agree, I don't see the reason to extend Array.protype, when wrapped code can be very readable as well. Besides, using underscore methods looks really sweet, when coding in Coffeescript:

_.each items, (item)-> item.doSomeStuff()
over 1 year ago ·

@paprikkastudio even sweeter without underscore:

item.doSomeStuff() for item in items

over 1 year ago ·

@greelgorke Of course! How could I forget that:D

over 1 year ago ·

Also, don't forget underscore's higher level methods. For instance, if you just want to call a method on each item, it'd be clearer to do: _.invoke(items, 'doSomeStuff'). Can use _.pluck to get a property off of a collection, etc.

over 1 year ago ·