DjebbZ DjebbZ - 3 months ago 10
Javascript Question

Why can't I chain String.prototype.toLowerCase with underscore.js?

I think the issue is not with underscore.js, but rather with Native prototypes functions. It seems that one can only call them directly, not passing them as callbacks. Here's the code the I can't use and the error from my tests (using Mocha.js, only the relevant portion):

_.chain("INPUT").tap(String.prototype.toLowerCase)
// => TypeError: String.prototype.toLowerCase called on null or undefined


So tried this in Node's REPL :

String.prototype.toLowerCase("INPUT")
// => ''


I know one should call a prototype's function with
.call
or
.apply
, but why exactly ? And how can I pass this function as a callback ?

Answer

Prototype methods are using this internally to refer to the object that should get manipulated.

call and apply lets you specify the this value when calling a function.

String.prototype.toLowerCase.call('INPUT'); //input

If you want to bind a this value to a function so that it's invocation form doesn't matter, you can do it with _.bind or Function.prototype.bind.

var lowerCaseInput = String.prototype.toLowerCase.bind('INPUT');

lowerCaseInput(); //input

Now, calling _.chain on an object will wrap it in an underscore object and returns the wrapper and _.tap takes the result of the previous function in the chain as it's input. Right here we see it's not going to work since String.prototype.toLowerCase doesn't even expect arguments.

Not only this, but strings are immutable so you would have to do something like the following:

_.chain({ text: 'INPUT' }).tap(function (obj) {
    obj.text = obj.text.toLowerCase();
}).value().text;