Hacker News new | ask | show | jobs
by hdhzy 3117 days ago
These kind of hidden extensibility in built-in functions make even seemingly simple code not work as expected:

  ["1", "2", "3"].map(parseInt)

  > [1, NaN, NaN]
5 comments

For anyone wondering why this is, it's because parseInt takes two arguments "string" and "radix".

Map calls a function with "currentValue", "index", and "array".

So the calls essentially look like this:

    parseInt("1", 0, arrayReference) // => 1
    parseInt("2", 1, arrayReference) // => NaN
    parseInt("3", 2, arrayReference) // => NaN
Can you please explain this? It makes no sense to me (as c# developer) that `["1", "2", "3"].map(parseInt)` whould get different result from `["1", "2", "3"].map(a => parseInt(a))`.

Why are they not equivalent?

EDIT: Never mind, another comment explained this.

I would argue this particular example has more to do with the radix parameter of parseInt being optional and having a complex behavior.

More generally, javascript functions accepting any number of parameters, regardless of those specified in the function declaration, is quite error prone when passing functions around.

I always use anonymous functions or 'bind' to explicitly match the parameters unless all functions involved are curried.

The other reason to avoid passing 'naked' functions around too happily is the behavior of this.

I also find most optimizations to focus on simple, explicit code. Nothing like using the less common, more dynamic features of the language to hit deoptimizations.

Yep, ["1", "2", "3"].map(x => parseInt(x)) works.
I wouldn't call it "hidden". If someone expected that to work, or couldn't figure out what the article example was doing, they just haven't read the documentation for 2 common functions. In fact, last I checked, always using the second parameter of parseInt was considered good practice.
There are generally two schools of thought: one is that the programmer should know better, memorize the documention and specs. The other one is that if it violates the principle of least astonishment it's just badly designed. Personally I believe that the truth is somewhere in the middle. It's good to know one's tools (including docs and specs) but I wouldn't call this kind of "clever" code maintainable.
You can work around this in lodash -- though of course it's not worth it:

  ["1", "2", "3"].map(_.bind(parseInt, null, _, 10));
  => [1, 2, 3]