skip to Main Content

I’m using UnderscoreJs. Consider this code:

var docs = [
    {name : 'Anders', niche : 'Web Development'}, 
    {name : 'Johnny', niche : 'Design'}, 
    {name : 'Eric', niche : 'PhotoShop'}
];

var newDocs = _.map(docs, function (doc){
    delete doc.niche;
    return doc;
});

It doesn’t matter if I use .each or .map here. The outcome is exactly the same.

What is really the difference between the two in the case above?

4

Answers


  1. _.each(list, iteratee)

    Iterates over a list of elements, yielding each in turn to an iteratee function.

    Each invocation of iteratee is called with three arguments: (element, index, list). If list is a JavaScript object, iteratee’s arguments will be (value, key, list). Returns the list for chaining.

    _.each({one: 1, two: 2, three: 3}, alert);
    => alerts each number value in turn...
    

    _.map(list, iteratee)

    Produces a new array of values by mapping each value in list through a transformation function (iteratee).

    If list is a JavaScript object, iteratee’s arguments will be (value, key, list).

    _.map({one: 1, two: 2, three: 3}, function(num, key){ return num * 3; });
    => [3, 6, 9]
    

    see documentation

    Login or Signup to reply.
  2. map is intended to be a functional mapping method: its function argument should return a value, but is not expected to have any side-effects.

    each is just a functional replacement for an imperative for loop: its purpose is to have an effect, and it is not expected to return any value.

    For example, this would be a more appropriate use for map:

    var docs = getDocs();
    var docTitles = _.map(docs, function (doc){
        return doc.title;
    });
    // expect `docs` to be unchanged
    

    Whereas this would be an appropriate use for each:

    var docs = getDocs();
    _.each(docs, function (doc){
        delete doc.niche;
    });
    // expect `docs` to be altered.
    
    Login or Signup to reply.
  3. Your assertion that the results are “exactly the same” is untrue. The _.each() function returns the original list, but _.map() returns a new list. You’re directly modifying the original objects as you go, so you end up with references to the same objects in each list, but with _.map() you end up with two separate array instances.

    Login or Signup to reply.
  4. You can just look at the source code to see the difference:

    • _.each:

      _.each = _.forEach = function(obj, iteratee, context) {
          if (obj == null) return obj;
          iteratee = createCallback(iteratee, context);
          var i, length = obj.length;
          if (length === +length) {
            for (i = 0; i < length; i++) {
              iteratee(obj[i], i, obj);
            }
          } else {
            var keys = _.keys(obj);
            for (i = 0, length = keys.length; i < length; i++) {
              iteratee(obj[keys[i]], keys[i], obj);
            }
          }
          return obj;
      };
      
    • _.map:

      _.map = _.collect = function(obj, iteratee, context) {
          if (obj == null) return [];
          iteratee = _.iteratee(iteratee, context);
          var keys = obj.length !== +obj.length && _.keys(obj),
              length = (keys || obj).length,
              results = Array(length),
              currentKey;
          for (var index = 0; index < length; index++) {
            currentKey = keys ? keys[index] : index;
            results[index] = iteratee(obj[currentKey], currentKey, obj);
          }
          return results;
      };
      
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search