2

I have a function foo that calls function bar. foo is bound to an element test.

When being called, bar stores its caller function (foo) inside the set s. When I now run the function foo inside s, strangely this is now set to Window. But I did bind the function, so what am I getting wrong?

var s = new Set();

function bar() {
  s.add(bar.caller)
}

var test = document.getElementById('test');
test.foo = (function() {
  bar();
  console.log(this);
}).bind(test);

test.foo(); // output: test div
s.forEach(fn => fn()); // output: Window object
<div id="test"></div>

6
  • Does this answer your question? How does the "this" keyword work? Commented Nov 13, 2019 at 7:38
  • "This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future." ~ MDN I can't tell you how it works cause it is implementation specific. Commented Nov 13, 2019 at 7:45
  • @JonasWilms Fair enough, but I would reckon it has nothing to do with caller as it seems to be poiting to the correct function. I thought it had something to do with how I then execute this function. Commented Nov 13, 2019 at 8:01
  • 1
    @SebastianKaczmarek Thanks, but it doesn't Commented Nov 13, 2019 at 8:03
  • @DonFuchs I suggest you analyze this answer: stackoverflow.com/a/3127440/7080548, especially the Examples part - 3rd example is pretty similar to what your code does Commented Nov 13, 2019 at 8:11

1 Answer 1

2

A bound function basically calls the function it is binding over¹ with the bounded this, so the callstack of your code looks like

 [Bound] test.foo -> test.foo -> bar

So from bar's point of view, it was called from test.foo not from the bound function.²


¹ as stated in the spec:

A bound function is an exotic object that wraps another function object. A bound function is callable (it has a [[Call]] internal method and may have a [[Construct]] internal method). Calling a bound function generally results in a call of its wrapped function


² wether function.caller returns the upmost callstack entry is not quite clear, as it is not specified. That's an assumption.

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

5 Comments

oddly enough logging bar.caller.toString() does give the source code of test.foo, but inside of bar, checking for strict equality (bar.caller === test.foo) returns false. Setting test.foo.dummy=2 gives undefined as well for console.log(bar.caller.dummy)
@user753642 bar.caller === test.foo returning false actually does comply with JonasWilms answer, because test.foo is the bound foo whereas bar.caller the unbound one
@user753642 And as for setting test.foo.dummy = 2 and reading it from bar, this is not working as you are again acting on the bound foo; if you set foo.dummy before binding, you can access dummy from bar too
@JonasWilms That makes sense to me, great answer
yes I overlooked the part : it was called from test.foo not from the bound function. I also checked foo.dummy which is indeed accessible from bar as "predicted"

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.