0

I'm learning about the hard binding in JS and experimenting with it. So I made my custom bind utility function and I'm using it upon the result given from the official JavaScript bind method.

function foo(a, b) {
  this.a = a;
  this.b = b;

  console.log(this.a);
  console.log(this.b);
}

function customBind(fn, obj) {
  return function(args) {
    fn.apply(obj, args);
  }
}

var obj = {
  a: 1,
  b: 2
}

var obj2 = {
  a: 2,
  b: 3
}

var myFunc = foo.bind(obj, 200, 300);
var myNewFunc = customBind(myFunc, obj2);
myNewFunc([400, 500]);

The result of this in the console is:

200
300

So what happens in this code? Can you explain the algorithm that the bind method uses to prevent this reassignment to me?

CertainPerformance
  • 260,466
  • 31
  • 181
  • 209
BoSsYyY
  • 493
  • 3
  • 11
  • 1
    change foo to `function foo(a, b, ...c)` - then add `console.log(this, c)` in `foo` - then you should see what is happening – Jaromanda X Jun 20 '18 at 10:08

1 Answers1

1

Please take a look at https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

If I were to code the bind functionality myself, it would look something like this:

Function.prototype.bind = function(thisArg, ...args) {

  // bind is a function on the Function's prototype, therefore it will be
  // in the 'this' variable of this function. For further reference see link 1. below.
  var originalFunc = this;

  // A new function is returned wrapping the original function. When this new function is
  // called it will call the original function with the thisArg and other args passed
  // to the bind function and appends the args passed to this new function after
  // the arguments passed to `bind`.
  return function(...secondaryArgs) {
     return originalFunc.call(thisArg, ...args, ...secondaryArgs);
  }
}

Note: This isn't entirely according to the spec, but it should give you an overal idea on how this would work.

As you can see calling the function returned by bind with another set of arguments (which is what you are supposedly are trying to do) does not replace the arguments passed to bind, but instead appends them at the very end.

This is why your example does not work as expected:

function foo(a, b) {
    console.log(a, b);
}

var newFunc = foo.bind({}, 200, 300);
foo(400, 500); // prints: 200, 300 instead of what you expected: 400, 500

Changing your example a bit to understand what is going on:

function bar(a, b, c, d) {
    console.log(a, b, c, d);
}

var newFunc = bar.bind({}, 200, 300);
newFunc(400, 500); // prints: 200, 300, 400, 500

Note the 400, 500 are appended after the 200, 300.

The following would also work:

var newFunc = foo.bind({});
foo(400, 500); // prints: 400, 500

Links

  1. How does the "this" keyword work?

Edit:

  • Apparently bind appends the arguments instead of ignoring them.
Kurzyx
  • 242
  • 3
  • 13
  • What about the new object (obj2)? Why doesn't the new object get passed as well? I think apply and call have some algorithm that checks whether the function is hard bound and if it's hard bound it ignores the new object. Is that the case? – BoSsYyY Jun 20 '18 at 18:14
  • I may have misunderstood your question at first. This may answer your question: https://stackoverflow.com/questions/20925138/bind-more-arguments-of-an-already-bound-function-in-javascript#answer-20925268 – Kurzyx Jun 23 '18 at 10:36