12

After reading through mozilla docs I found this:

In the global execution context (outside of any function), this refers to the global object, whether in strict mode or not.

After playing with scopes for a little I found that in node.js REPL...

> this === global
true

but when I create a script with the same line...

$ cat > script.js
console.log(this === global)
$ node script.js
false

Is there a reason for this? Or is it a bug?

Maciej Goszczycki
  • 1,118
  • 10
  • 25

2 Answers2

13

Node's REPL is global. Code from a file is in a "module", which is really just a function.

Your code file turns into something like this very simplified example:

var ctx = {};
(function(exports) {
    // your code
    console.log(this === global);
}).call(ctx, ctx);

Notice that it's executed using .call(), and the this value is set to a pre-defined object.

cookie monster
  • 10,671
  • 4
  • 31
  • 45
  • And indeed, `console.log(this === exports);` logs `true`. Interesting. I don't think "Nodes REPL is global" really answers why REPL is calling the code you enter with `this = global`, but this nicely explains what `this` is in modules. Is this in the documentation somewhere? – T.J. Crowder Dec 31 '13 at 17:41
  • OK that sure makes sense. – Pointy Dec 31 '13 at 17:41
  • 1
    @T.J.Crowder: I don't know if it's documented. I learned how it works by reading the source. This is also how Node is able to make a `require()` idempotent. The `ctx` object is cached and returned on subsequent calls. – cookie monster Dec 31 '13 at 17:42
  • ...and by "`REPL` is global", I mean that the code provided is executed in the global scope, and so its `this` is the global object whether or not we're in strict mode, as described by the MDN reference. – cookie monster Dec 31 '13 at 17:44
  • @cookiemonster: :-) Node's docs still, years later, leave a *lot* to be desired. Ah, well... Maybe someday I'll know Node well enough to help improve that situation, though it always irks me to go back and document other people's stuff. – T.J. Crowder Dec 31 '13 at 17:44
  • @cookiemonster: *"...and by "REPL is global", I mean..."* Which I expect isn't documented anywhere either. :-) – T.J. Crowder Dec 31 '13 at 17:44
  • @T.J.Crowder: Yeah, I stopped using Node (for the most part) about a year ago. Using Go now *(or maybe I should say "for now")*. :-) – cookie monster Dec 31 '13 at 17:45
  • @cookiemonster how would one reference the current context if you cannot use this? For example `var cs = {}; console.log(this.cs); //undefined` when ran via `node test.js` – WORMSS Dec 09 '14 at 13:13
0

When you use node to run script from a file, it implicitly sets it up as a module with its own scope.

When you just run it without a file, you're dropped into the REPL but not in any module scope.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • 1
    That's true, but it doesn't explain `this`, as `this` in the script is not referring to the module's scope (that is, the variable binding object for the execution context of that execution of the module). E.g. `var x = 42; console.log(this.x);` logs `undefined` in a script. I'm not immediately finding anything saying what `this` is in a module (it logs as an empty object), or anything saying that REPL evaluates your code with `this = global`. – T.J. Crowder Dec 31 '13 at 17:37
  • @T.J.Crowder yes I'm a novice Noder at this point, so I'm not exactly sure what Node is doing. It's never occurred to me to *try* to access the scope via `this`, but of course that's why Stackoverflow questions exist :) – Pointy Dec 31 '13 at 17:39
  • @T.J.Crowder however from the plain REPL you get from just running `node`, it sure does seem like `this` is global, and if you try that `var` test it does too: `var foo = "hello world"; global.foo;` prints the right value. – Pointy Dec 31 '13 at 17:40
  • Yeah, REPL is definitely executing the code with `this = global`. – T.J. Crowder Dec 31 '13 at 17:42