1

In the explanation of arrow functions, w3schools says, "In regular functions the this keyword represented the object that called the function, which could be the window, the document, a button or whatever" and "With a regular function this represents the object that calls the function". Link: https://www.w3schools.com/js/js_arrow_function.asp

I'm trying to understand this sentence, not in relation to arrow functions but by itself. It seems that many other sources I found on the net contradict to this, saying that when a function gets called on its own (not as a method), 'this' gets bound to either the toplevel object (e.g. window) or undefined, depending on strict mode.

So I built a simple example (running non-strict in the browser). I did not want to use the examples from the w3schools site because they use event handlers for explanation, and I want to make sure that I avoid any additional binding logic that event handlers introduce.

<script type="text/javascript">

function foo() {
    console.log('foo on ' + this.prop);
}

function bar() {
    console.log('bar on ' + this.prop);
    var f = this.foo;
    f();
}

var x = {
    prop: 'x'
};
window.prop = 'w';

x.foo = foo;
x.bar = bar;
x.bar();

</script>

This logs: "bar on x" and "foo on w", which seems to indicate that in foo, this refers to the window. So obviously the w3schools explanation does NOT refer to an automatic binding of foo's this to bar's this when foo gets called inside bar. But what else does it mean?

Martin Geisse
  • 800
  • 1
  • 6
  • 18

1 Answers1

3

Well, let's start with the premise that W3Schools has a less than stellar reputation and you shouldn't be thinking too hard about whatever it is they're writing. In fact, you should preferably read MDN instead.

In regular functions the this keyword represented the object that called the function...

Well, yeah, no… An object doesn't call anything. An object just is. It's a container of other stuff. One such "stuff" may be a function. You may then have code which takes the function from that "container" and calls it. So, code calls functions, whether those functions are a property of objects or otherwise.

How this is determined inside that function depends on exactly how that code calls the function. In a nutshell, in the expression a.b(), this inside b will be a. As a general rule, this inside a function will be whatever came before the . when it was called.

If there was no . before its call, e.g. just b(), there's no this (how that manifests exactly depends on the strict mode). It doesn't matter whether that function was originally part of an object or not; all that matters is the exact expression that was used to call it.

For all the gory details, you can see How does the “this” keyword work?.

The footnote here being that you can bind this on a function or pass another this explicitly using call or apply, and fat arrow functions don't follow this rule at all.

deceze
  • 471,072
  • 76
  • 664
  • 811
  • Using the terminology from the other question your linked to: Lets assume that a (non-arrow) function that was not bound using bind() gets called directly (not through call or apply), and gets called without a dot. Is there any case, in strict or non-strict mode, where the thisBinding of the new execution context gets set to the thisBinding of the calling execution context? Not talking about cases where they just happen to be the same, such as when 'this' is the toplevel object (window) in both. IOW, is there a case where such a call desugars to func.call(this, ...)? – Martin Geisse Jan 31 '20 at 13:16
  • Not that I know of, no. The value of `this` in the scope of the caller never automatically gets inherited by functions that are called from it. That's exactly why `=>` functions were invented, because it's such a common use case that was not directly addressed in the original spec. – deceze Jan 31 '20 at 13:18
  • This is not actually part of the question, but to avoid confusing anyone who reads this: AFAIK the arrow functions inherit 'this' from the place they are defined (lexical closure), not from where the function is called. Anyway, the actual answer to the question seems to be that w3schools is simply wrong here. – Martin Geisse Jan 31 '20 at 15:20