Rafi Henig
Rafi Henig

Reputation: 6422

Why bind.apply(fn, arguments) omits the first argument when passed arguments object?

I bumped into an unexpected js behavior when I passed bind.apply() an arguments object as second argument, it seems like it omits the first argument as it executing the function.

function func(fn){
    console.log(arguments) // [ƒ, 4, 4]
    return fn.bind.apply(fn, arguments)
}


function add(a,b,c){
    console.log(arguments) // [4, 4]
    return b + c // c is undefined
}

let foo = func(add,4, 4)
foo() // NaN (expected 8)

Upvotes: 1

Views: 111

Answers (1)

Phil
Phil

Reputation: 164901

The issue is that Function.prototype.bind() accepts one or more arguments

(thisArg[, arg1[, arg2[, ...]]])

When you use Function.prototype.apply() with arguments (fn, [fn, 4, 4]), you are doing two things...

  1. Binding the Function.prototype.bind this context to fn, and
  2. Calling bind(fn, 4, 4)

Do you now see the problem? bind(fn, 4, 4) will create a new function, bound to fn for its this context and with default arguments (4, 4).


If you really want fn to appear as the first argument to itself (which sounds like a bad idea to me), I find the spread operator much easier to understand

function func(fn, ...args) {
  return fn.bind(fn, fn, ...args)
  //             ^   ^   ^
  //             |   |   |
  //             |   |   args #2, #3, ...
  //             |   arg #1
  //             this
}

Upvotes: 1

Related Questions