27

Please explain usage of _.identity(value) of underscore.js. Not able to understand it from the documentation ( http://underscorejs.org/#identity ).

Can you provide some example of its usage?

SunnyShah
  • 28,934
  • 30
  • 90
  • 137

3 Answers3

46

A JavaScript code pattern involving identity is filtering values based on truthiness, e.g.

var a = [null, null, [1,2,3], null, [10, 12], null];

a.filter(_.identity) 

yields [Array[3], Array[2]].

Using

_.compact(a)

is clearer, but one may not use lodash or underscore at all, e.g.

function identity(x) { 
   return x; 
}

a.filter(identity)

Whether it is a good code pattern is questionable for several reasons, but it's being used in the wild.

It is not a NOOP at all. A NOOP is an imperative construct in e.g. assembly, whereas in functional programming, it is like other functions in that it returns a value. If identity were a NOOP, then all pure functions could also be considered noop, and it would not be a sensible thing.

Robert Monfera
  • 1,980
  • 1
  • 22
  • 16
15

It's essentially a no-operation function. It returns the value of whatever was passed into it.

The part about it being used as a "default iterator" within the library itself means that in other functions which may have an optional "iterator" parameter (which is likely used as a function to apply to each element of an array of some kind), if no iterator parameter is passed, the library will use this "no-op" iterator instead and the elements of the array will remain unchanged.

Matt Sach
  • 1,162
  • 16
  • 37
  • 4
    Just for the sake: You can see this noop in the [the annotated source](http://underscorejs.org/docs/underscore.html#section-118). – dan-lee Jan 08 '13 at 14:01
  • @SunnyShah It's not my answer, just my comment. I think you can mark the answer fromm Matt in a few minutes. – dan-lee Jan 08 '13 at 14:04
  • @DanLee, But your comment became an answer for me. :) – SunnyShah Jan 08 '13 at 14:05
  • Thanks @DanLee. A good illustration of usage inside the library is http://underscorejs.org/docs/underscore.html#section-20, see the first line of the _.every() function :) – Matt Sach Jan 08 '13 at 14:07
  • This doesn't really explain why it exists. – Code Whisperer Oct 01 '13 at 23:19
  • I think it does: it exists so that it can be used internally in the library as a default "do nothing" operation for functions which have an optional function parameter. – Matt Sach Oct 04 '13 at 11:57
  • 1
    If you think about it, this is also similar to [Null Object Pattern](http://en.wikipedia.org/wiki/Null_Object_pattern) in OO. Instead of having an if statement to do different functionality if the param is null, the default functionality is in identity and the rest of the library code doesn't have to worry about it. – ShawnFumo Nov 11 '13 at 21:42
13

A specific example:

Underscore.js defines _.each and as like this.

_.each = function(obj, iterator, context) {
  ...
}

This iterator shows el value. You maybe have used this idiom.

_.each([1, 2, 3], function(el){
  console.log(el);
});

This iterator returns el value without change.

_.each([1, 2, 3], function(el){
  return el;
});

The function that returns a value without change occur frequently. So Underscore.js wants to define the function. Underscore.js names the function _.identity.

_.identity = function(value) {
  return value;
};

If Underscore.js wants to use a default iterator, all Underscore.js need is call _.identity.

_.each([1, 2, 3], _.identity);
Teruki Shinohara
  • 783
  • 1
  • 9
  • 12
  • Using _.each purely to return something is not suggested, this is what _.map is for: `_.map([1, 2, 3], function(el){ return el; });` It's good to signal your intent with your code. JavaScript's analogous forEach and map are better separated, as forEach doesn't collect function results even if there's a return statement in it. – Robert Monfera Jul 04 '15 at 09:24