0

NodeJs:

function foo() {
  console.log(this === global); // true
  }
foo();
console.log(global.foo); //undefined

this inside a function refers to the object on which function was invoked. So from above code I expect foo to exist on global object but that is not the case. Can anyone explain this behaviour?

mustafa1993
  • 349
  • 1
  • 3
  • 12
  • 1
    That's the way JavaScript works. The value of `this` is a reference to `global` because the function is called without any other source for `this`. If you were in "strict" mode, the value of `this` would be `undefined`. – Pointy Sep 26 '20 at 12:43
  • Ok, so on which object foo is defined on then? As in browser it's attached to window object (yes except in case of let, const expression in which case I have the same question). In my mental model I always imagine a function to exist on some object (which is window/global in case of global scope declaration). Can you explain or point to some resource? Thank you – mustafa1993 Sep 26 '20 at 12:56
  • What I mean is if I declare same function in browser in global scope, it's attached to window object. – mustafa1993 Sep 26 '20 at 12:59
  • 2
    Well there is no `window` object in Node. Functions in JavaScript are not really "on" objects the way methods in languages like C++ or Java are. What matters is how a function is *called* in JavaScript. – Pointy Sep 26 '20 at 13:01
  • if you want `this` not to be equal to `global` then you have to bind the function – aRvi Sep 26 '20 at 13:02
  • 1
    You might want to have a look at [How does the “this” keyword work?](https://stackoverflow.com/q/3127429/8289918) – cherryblossom Sep 26 '20 at 13:15

1 Answers1

2

In non-strict mode in Javascript (often called "loose" mode), when you call a function as a regular function such as foo(), the this value will be set to the global object.

In strict mode in Javascript, when you call a function as a regular function such as foo(), the this value will be set to undefined.

Based on the results in your question, you are apparently running in non-strict mode so the this value inside your function is set to the global object when called as foo(). The function declaration itself in node.js is inside a module so that function has module scope, not global scope and thus the function itself is not a property of the global object. The this value has only to do with the fact that it was called as foo() in non-strict mode.

Keep in mind that the this value in a function in Javascript is entirely determined by how the function was called (and in the case of arrow functions, how it was declared). You can see the six ways that the value of this is controlled or determined inside a function call here in this answer.


Now, for your specific questions:

this inside a function refers to the object on which function was invoked.

That would be true if the function was called as in obj.foo() and foo was defined as a property of object obj. But, that does not apply when it is called as foo() and foo is declared as a stand-alone function (not a property on a specific object).

So from above code I expect foo to exist on global object but that is not the case. Can anyone explain this behaviour?

Whether foo exists on the global object or not is determined by how foo is defined, not how it is called. It has to either be specifically assigned to the global object or declared in the global scope. In your specific example in node.js, foo is declared within module scope (which is actually within a module function) so it is local to that module scope and is not global.

jfriend00
  • 580,699
  • 78
  • 809
  • 825
  • Thanks this clears lot of things. I got how this value is determined inside function, but then is it true that stand-alone function, such as foo here, is not defined as property of ANY object, they just .. exist ... in global scope (not even on window/global object in non-strict mode). I cannot find it even on module.exports – mustafa1993 Sep 26 '20 at 18:07
  • 1
    @mustafa1993 - The code in a commonJS module in node.js exists inside a [module function wrapper](https://nodejs.org/api/modules.html#modules_the_module_wrapper), so your function `foo()` is just a local function in that module function scope. It is NOT a property of any accessible object (technically, it's attached to some sort of internal scope object, but that object is not accessible to user Javascript). So, just like when you define a variable in a function as in `let x = 2;`, `foo` just exists in the current scope. – jfriend00 Sep 26 '20 at 18:26
  • Thank you. I don't know why question get's marked as duplicate. Though similar posts explain 'this' fairly but not the answer I am looking for. Your answer clarified things. – mustafa1993 Sep 26 '20 at 18:36
  • @mustafa1993 - Well, the `this === global` is entirely explained in multiple duplicates which is probably what triggered those. But, the `global.foo` aspect of the question is not explained in those same duplicates. – jfriend00 Sep 26 '20 at 18:39