admin管理员组

文章数量:1277400

given an array of objects

l = [a,b,c,d]

l.map(function(x){x.zop({foo:bar})})

is this a bad idea?

i mean it works and all :D

given an array of objects

l = [a,b,c,d]

l.map(function(x){x.zop({foo:bar})})

is this a bad idea?

i mean it works and all :D

Share Improve this question edited Feb 18, 2012 at 4:36 samccone asked Feb 18, 2012 at 4:28 samcconesamccone 10.9k7 gold badges44 silver badges50 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 8

Yes, it is perfectly fine to use array iteration functions and I personaly try to use them whenever I can instead of a for loop. The main reasons I do so are:

  • No need to declare useless variables (like the loop counter) that clutter the code and confuse my JSHint.

  • I need to write down the array only once. This makes it easier to rename the array variable if I want to and it is also more amenable to passing an expression directly (instead of having to save the array in aother extraneous variable)

  • Regular for loops are vulnerable to the closures-inside-for-loops bug.

Do remember though that map, forEach and friends are not present in older browsers (particularly, Internet Explorer) so you should either use a shim (to add these methods to the native arrays) or use similar functions from a custom library.

edit: nowadays you should feel free to use these functions. If you still need to support IE8 you have bigger problems than this...

If you want to support old browsers without using shims, it's a bad idea.

If you don't mind dropping support for old browsers or loading shims to make them make them work, it's fine.

On the other hand, some argue that using shims is a bad idea. If that's the case, and you need to support old browsers, then map is a bad idea. Personally, I'm still on the fence about the shim issue.

Also, I'm not sure if this is relevant, but be aware that jQuery's map will flatten arrays, which is not what map functions normally do, so some folks consider that implementation to be broken.


Just for fun, here are some counterarguments to missingno's arguments for iteration functions.

No need to declare useless variables (like the loop counter)

Loops don't always have to have counters. When you're dealing with disposable arrays of objects, for example, loops like this work nicely:

var things = [{foo:1}, {bar:2}, {foo:3}, {bar:4}], item;
while (item = things.shift()) {
    console.log(item);
}

In a regular for loop I have to type the array name multiple times (so its more work if I want to rename it)

In the example above, we only had to type the array name once after it was declared. Even with a non-disposable array, where we'd need a counter for our loop, we still wouldn't need to type the name of the array any extra times.

Regular for loops are vulnerable to the closures-inside-for-loops bug.

Yeah, you got me there :)

If you're using jQuery, this isn't a bad idea at all, but the standard pattern is to use .each():

var $l = $(selector);
$l.each(function(){ $(this).css({foo:bar}) });

The main difference is that .map() is intended to return an array of modified objects, whereas .each() just runs a function on each object - so it's conceptually closer to what you're trying to do, and probably more efficient (because it doesn't need to create the return array).

This assumes that your "array of jQuery objects" is in fact a jQuery object itself (that would be the standard approach). If not, you can use .forEach() instead - this is the standard Array method.

If you're just talking generally about arrays, there are a couple of points to consider:

  • As others have noted, older browsers don't support .map() and .forEach() natively, so you'd need some kind of shim or polyfill if you're looking to support those environments.

  • One good thing about .map() and .forEach(), however, and one of the reasons I use them more often than for loops, is that they give you a new function scope within the loop. This means that you can create closures within the loop that reference the current item, which is a total pain with a for loop. For example:

    list.forEach(function($item) {
        $item.click(function() {
            alert("This is item " + $item.data('name'))
        })
    });
    

    (This is a bit of a red herring with jQuery, because you can use $(this), but there are lots of places where it's quite useful.)

  • Using .map() and .forEach() allows you to reuse the function if you like, in a way that's possible but less elegant in a for loop:

    function foo($item) { $item.css({foo:"bar"}) }
    list.forEach(foo);
    anotherList.forEach(foo);
    
  • This is just personal preference, but I find the syntax and style more elegant in general than a for loop, and you avoid putting an iteration variable like x in the current scope.

  • When you're dealing with nested structures, you get to give each level a descriptive name if you use .map() and .forEach(), which makes your code more legible. For example:

    states.forEach(function(state) {
        state.forEach(function(county) {
            county.forEach(function(city) {
                alert(city + ', ' + county + ', ' + state);
            })
        });
    });
    

    Compare to nested for loops, where your inner alert statement would look something like:

    alert(cities[x] + ', ' + cities[x][y] + ', ' + cities[x][y][z]);
    

本文标签: javascriptis using map instead of a for loop a bad idea in JSStack Overflow