3

I'm trying to understand the below code which prevents bugs caused by a function silently passing to a call back function more arguments that aren't wanted in the parameters of the callback function:

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

returns [1, NaN, NaN] because the index gets passed as a second parameter to parseInt which accepts it as the radix, so the array values are invalid. To solve it, the author of this blog post suggests a js extension:

Function.prototype.only = function(numberOfArgs) {
   var self = this; //the original function
   return function() {
      return self.apply(this,[].slice.call(arguments,0,numberOfArgs))
   }
}; 

Which would be called like so:

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

I'm struggling to understand why "this" is passed as a function parameter while self is returned as a reference to this. They both point to parseInt correct? Is there a difference in binding times of parameters vs return values?

user5389726598465
  • 1,217
  • 1
  • 11
  • 22

2 Answers2

2

They both point to parseInt correct?

No.

The value of this depends on how a function is called.

The function passed to map gets called by the internals of map.

Look at the documentation for map.

If a thisArg parameter is provided to map, it will be used as callback's this value. Otherwise, the value undefined will be used as its this value.

So if the returned anonymous function used this instead of self it would be calling undefined.apply not parseInt.apply.

Quentin
  • 800,325
  • 104
  • 1,079
  • 1,205
1

I'm struggling to understand why "this" is passed as a function parameter while self is passed as a reference to this. They both point to parseInt correct?

No. self will refer to parseInt. this will be whatever this the function was called with, which could be anything. In your example:

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

...this will either be a reference to the global object (in loose mode) or undefined (in strict mode), because map will use undefined when calling the callback (which is turned into a reference to the global object in loose mode).

There are several ways this might be something else though:

  1. If a second argument were passed to map:

    ["1","2","3"].map(parseInt.only(1), {})
    // Second argument -----------------^^
    

    ...it would use that value rather than undefined when calling the callback.

  2. If Function#bind were used on the function only returns:

    ["1","2","3"].map(parseInt.only(1).bind({}))
    // Bind ---------------------------^
    

    ...then this would be that value.

  3. If the function only returns were called with call or apply (which is what map does, so this is kind of a repetition of #1 :-) ), the value supplied for this would be used.

T.J. Crowder
  • 879,024
  • 165
  • 1,615
  • 1,639