0

While I was working with the bind() function, I came across a situation I am currently not aware of. Can someone give me and explanation why this example works like this? Apparently the inline object passed to the bind function is initialised only in the first iteration and then a reference is kept. I was not able to find any documentation about this, if you can point me to the right direction I will be veeeery grateful :-)

class test {

 addLetter(element) {
  console.log('addLetter', this.str);
  this.str += element + ',';
 }

 foo() {
  let arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];

  arr.forEach(this.addLetter.bind({
   str: ''
  }));
 }
}

let a = new test();
a.foo();

OUTPUT:
addLetter 
addLetter a,
addLetter a,b,
addLetter a,b,c,
addLetter a,b,c,d,
addLetter a,b,c,d,e,
addLetter a,b,c,d,e,f,
3
  • Possible duplicate of How does the "this" keyword work? Commented Aug 28, 2017 at 9:20
  • 1
    Your code can be deconstructed to let cb = this.addLetter.bind({...}); arr.forEach(cb);. – Yes, you're only ever creating one callback with one bound object. Commented Aug 28, 2017 at 9:22
  • Indeed, my error was considering the forEach as a normal loop, thanks. Commented Aug 28, 2017 at 11:48

2 Answers 2

1

It's easier to see if you separate the argument from the function call. A function call like:

someFunc(<expression>);

is equivalent to:

var tempVar = <expression>;
someFunc(tempVar);

So in your case, it's like this:

var tempVar = this.addLetter.bind({
   str: ''
});
arr.forEach(tempVar);

This makes it clearthat we're only calling bind() once, when we set tempVar. It creates a function that's bound to a specific object. Then forEach calls that function repeatedly. We can further break it down to:

var tempObj = { str: '' };
var tempFun = this.addLetter.bind(tempObj);
arr.forEach(tempFun);

Now it should really be clear why there's just a single object that gets reused each time the function is called.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much, deconstructing it really makes it very easy to understand :)
1

the first argument to .bind() is the context. In this case it is the

{
    str: ''
}

Now, you are referencing it and using its str property within. Now, we know .bind() returns a function. That function happens to be called within .forEach().

This bind generated function receives as its first argument an element (depending on the iteration).

For the first time iteration index is zero and the bind generated function function receives 'a' as its argument.

Statement

this.str += element + ',';

enhances str as '' + 'a'. In the second iteration, the argument is 'b' and that gets appended to 'a,' + 'b' and so on.

Hence you see the result you see. Let me know if this clarifies your question.

5 Comments

why does bind pass the same anonymous object in all iterations but does not create an object for each iteration?
That is a good question. So, what is bound is a reference to an anonymous object and in the loop you happen to only change its str property. There is no new object created with each loop iteration that is why the str property of the same object continues to grow (through concatenation).
@Dmitry Because bind isn't aware of any loops. It only binds the object once, because it's only called once.
Ah, now I see. I was perceiving the forEach as a normal loop and that confused me.
Me too, instead of treating it as a callback I was simply considering it as a normal execution inside a loop/ :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.