user3246794
user3246794

Reputation:

Why doesn't underscore use typeof for detecting functions?

Here is the relevant code:

// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
  _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
    _['is' + name] = function(obj) {
      return toString.call(obj) === '[object ' + name + ']';
    };
  });

I can understand why toString is used in these other cases, but

typeof function(){}

and

typeof new Function()

will return function

is there a use case that I am missing.

typeof should be faster and just as accurate in this case.

Upvotes: 0

Views: 286

Answers (2)

The Spooniest
The Spooniest

Reputation: 2873

Faster, yes, but it turns out to be not quite as accurate in practice.

Although typeof obj === 'function' works in most cases, some browsers do strange things in the edge cases, especially with native objects. There are a few questions here that go over some of the more bizarre cases (and they're really bizarre, but they're out there): things like elements containing objects from plugins and such. The end result is that there are a very few object/browser combinations out there that get this wrong in a couple of cases: when using typeof, either they detect as functions when they shouldn't, or they don't detect as functions when they should.

For most code, this doesn't matter much. Like I said, we're talking about edge cases here. But libraries like Underscore can't afford to be wrong in the edge cases: they need to be sure they get it right in every case, even if the browser gets it wrong. And for whatever reason, even the browsers that get typeof wrong all seem to get Object.prototype.toString(obj) right. So Underscore uses that trick, because it's the simplest method that works everywhere. It also dovetails well with cases like Array, where you have to use this method because typeof just plain doesn't work.

Upvotes: 3

zzzzBov
zzzzBov

Reputation: 179046

Underscore uses a method that is consistent so as to avoid micro-optimization and improve readability and compressibility.

Treating _.isFunction differently for the sake of a couple microseconds doesn't make sense unless _.isFunction is an actual bottleneck in actual code.

Upvotes: 1

Related Questions