Chaining .apply() and .bind() surprising behaviour

bind javascript w3schools
javascript bind null
javascript bind event
bind call, apply
javascript apply
call vs apply vs bind
javascript call
javascript bind this to callback

I need your help to better understand the following behavior.

In the snippet below, we can see that fooBar outputs foo as this and then returns bar 1, 2, 3 as expected - means bar is called with foo as context.

const arguments = [1,2,3];

function bar(...args) {
  console.log('bar this ->', this);
  return 'bar ' + args;
}

function foo(...args) {
  console.log('foo this ->', this);
  return 'foo ' + args;
}

const fooBar = bar.bind(foo, null)(arguments);

console.log(fooBar); // <--- no surprises!

This is because of the specific purpose of apply: to call a given function. Remember that bar is the generic Function.prototype.apply function.

bind essentially creates a copy of the original function, with the context (this value) and (optionally) arguments preset. A polyfill for bind would use apply internally.

So fooBar = bar.bind(foo, null) is the same as

function fooBar(...args) {
    return Function.prototype.apply.apply(foo, [null, args]);
}

The double use of apply is obviously confusing!

Let's step through what bar.bind(foo, null)(arguments) would do:

Function.prototype.apply.bind(foo, null)(arguments)

which can be reduced to

Function.prototype.apply.apply(foo, [null, arguments])

which in this specific instance is the same as

foo(null, ...arguments);

The reason this is so confusing is that you are doing a complex invocation of the apply function, which is designed for complex invocations of functions!

Chaining Function.apply.bind() in Return Largest Number in Arrays , The major issue I am having trouble grasping is the behaviour of how Function.​apply() or Function.bind() works versus an explicitly defined  You can define a default behavior which can be shared across all services or endpoints running on a machine or within a solution through machine.config file / application configuration file. In WCF 3.x , you have to define named behavior configurations first, then you apply the same explicitly to the service and points through the “ behaviorConfiguration ” attribute.

bind is creating a new function which calls its this value (bar, which is a copy of apply) with the value you pass to it as the new this value.

Since bar is a copy of apply:

bar.bind(foo)() is the same as foo.bar() is the same as foo.apply().

How to use the apply(?), call(?), and bind( ) methods in JavaScript, In this article, we'll talk about the apply, call, and bind methods of the function and properties through the prototype chain from Function.prototype. The apply​() method is an important method of the function prototype and is An interesting thing to point out here is that in place of this we have used null. The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called. The source for this interactive example is stored in a GitHub repository.

Let's make our own "makeshift" myApply that mimics the native Function#apply to better understand how Function#apply works.

Function.prototype.myApply = function(args) {
    // some checks should be here to see if 'this' is a function and if 'args' is an array-like
    this(...args);
}

It takes an array (or array-like object) containing the arguments and calls this (whatever myApply is applied to) which should be a function with each item from args passed as a standalone argument.

The simple example:

Now when you do:

alert.myApply(["hello, there"]);

alert is passed as this to myApply (self explanatory), and ["hello, there"] is passed as args and everything works as expected.

The confusing example:

Now when you explicitly set the this of myApply using bind, call or even apply like so:

var myApply = alert.myApply;

var newFunction = myApply.bind(foo);

newFunciton becomes a new function (a function that is equivalent to myApply bound to foo). Calling newFunction is like calling myApply with its this set to foo. When myApply is called, its this value (which is foo in this case) will be called.

Additional note: As you can see myApply doesn't mess around with the context of its this (which is a function), so that function will be called with whatever context it was before myApply is called, in this particular example it's the global object window (foo's this is window).

Understanding this and .bind(), You realize that the this keyword in your makeButtonLightUp() Alternatively, you might call .bind() on your your function just to keep things interesting. Both effect the behavior of your code in different ways. But, if you declare a function within another function, you create what's called a scope chain. Understanding the available syntaxes of arrow functions will give you an understanding of what behaviour they are introducing when 'chained' like in the examples you provided. When an arrow function is written without block braces, with or without multiple parameters, the expression that constitutes the function's body is implicitly returned.

Function.prototype.bind(), The bind() method creates a new function that, when called, has its this keyword const slice = Array.prototype.slice; // slice.apply(arguments); not rely on those cases where behavior deviates from ECMA-262, 5th edition! The less surprising behaviour can be achieved by using the method invocation pattern of calling functions. Method invocation pattern. If there are dots in your function call, your function context will be the right-most element of your dots chain.

DNA Engineered Noble Metal Nanoparticles: Fundamentals and , It is therefore not surprising that DNA with a linear charge density of 0.59 e-Å-1 (​in to anionic polyelectrolytes of high charge density underlines this behavior [​76]. of longer-chained surfactants was required to start the binding to DNA [738​],  Command Binding with Events. If you have followed me this far then you should have some idea about how to bind a control with a command and if a control don’t have any suitable property to bind with then we can make one (attached property). Now we are pretty close to binding an event with a custom command in your viewmodel.

Chained By Fear, As ifinresponse tothe sorcerer's strange behavior, the chains binding him had begun toweaken, the will that engorged them fading until they became mere metal,  Footnote: the "same property source" rule doesn't apply to maps. You can bind to Map<String,String> (for instance) with property values drawn from multiple sources. That makes total sense too, it just highlights that the list behaviour is surprising.

Comments
  • Why did you choose Math.max.apply exactly? It has no effect at all, it is the same as doing const bar = Function.prototype.apply; or const bar = alert.apply, or any other function for that matter: you are just referencing the method apply of the class Function.
  • no particular reason for this choice apart from: to confuse myself even more
  • @lustoykov Maybe you mean const bar = Function.prototype.apply.bind(Math.max)
  • thanks @Bergi, this is not what confuses me. I think the answer from @lonesomeday is closest for me to understand, but something doesn't add up, since Function.prototype.apply.apply(foo, null)(arguments) is not a correct syntax
  • @lustoykov Also notice that .bind(foo, null)(arg) is not correct anyway. It should be .bind(foo)(arg) or .bind(null)(arg)
  • thank you so much for the input! I'm on the road now and will look more closely when I'm home. Sounds like the correct answer though!
  • hey, thanks for the input! Your last sentence is correct, but I'm afraid only for the case where bar is Function.prototype.apply, here is a counter example: jsbin.com/maxinuwoto/1/edit?js,console. That's what I'm trying to understand - why does it behave differently in this case.
  • Why does it behave differently when it is apply though? Hmm... what is bind() doing exactly under the hood? If I could find the implementation somewhere! The statements are correct and that's what I've concluded as well, but I don't understand why
  • It doesn't behave differently with apply. apply just does what it does given the this value it gets.
  • @lustoykov Actually your jsbin example is not what Quentin is trying to say. For it to be the same bar shound be apply (ie const bar = Function.prototpe.apply;.