2

I have Node.js v8.10.0 locally installed. I wrote a simple script to play with 'this':

var x = 1;

var fn = function (a) {
     var x = a;

     console.log(`local x = ${x}`);
     console.log(`global x = ${this.x}`);
}

fn(10);

When I execute script via Node.js I get following result:

local x = 10

global x = undefined

When I execute script in Chrome I get the following result:

local x = 10

global x = 1

Could you please explain to me, why Node.js doesn't see x in global scope?

Liam
  • 27,717
  • 28
  • 128
  • 190
ProximaCygni
  • 887
  • 1
  • 6
  • 9

2 Answers2

7

Could you please explain to me, why Node.js doesn't see x in global scope?

It does, if you run it in Node console. If you run it in as a file, x is in the file's scope, not global scope.

By the way, in Node, you can use global to explicitly see the global scope, just like you'd use window in a browser. Thus,

console.log(global == this)

will give you two different answers depending on whether you run it in a file or in a console.

Also, try to migrate to let and const. This is extra confusing because var behaves differently in global scope and elsewhere. In console and in browser, your outer var x is in global scope, so it defines a global variable (window.x and global.x). In a Node file, var x is not in a global scope, so it does what it normally does when not in global scope: defines a local variable x (not this.x, not global.x, just x). Thus, you have two local variables, the inner one shadowing the outer one, which makes the outer one inaccessible. Meanwhile, this.x has never been defined.

Amadan
  • 191,408
  • 23
  • 240
  • 301
  • Thanks a lot for the explanation and giving me a hint about file's scope! I also just tried to remove `var` from the outer `x` and now `x` belongs to the `global` scope. I already heard about `let` and `const` - I learn different aspects/tricks of javascript now, so I try to dig deeper to have a better understanding how it works. – ProximaCygni Jul 24 '18 at 09:01
  • 1
    Yep. If no definition of `x` is present, and you are not under `"use strict"`, then `x = ...` will assign to `global.x` or `window.x`. It is best not to rely on it, always use `"use strict"`, and always assign to `global.x` or `window.x` if you explicitly want a global variable. – Amadan Jul 24 '18 at 09:05
3

In chrome this is a object of Window as if you do this.constructor.name you get Window as a constructor name so while accessing this.x it will look for the global variable x and does not reference to the function scope.

var x = 1;

var fn = function (a) {
     var x = a;

     console.log(`local x = ${x}`);
     console.log('Constructor ', this.constructor.name);
     console.log(`global x = ${this.x}`);
}

fn(10);

However, in NodeJS, this will always refer to the function prototype (not the global scope). Thus, you do not have any value x associated with the prototype of the function so it gives you undefined.

Ankit Agarwal
  • 30,378
  • 5
  • 37
  • 62
  • "However, in NodeJS, this will always refer to the function prototype (not the global scope)" This is not correct. Neither prototypes nor constructors are involved here. If you run the code in node REPL (simply invoking `node` in shell and pasting the code) you will get the exact same output as in Chrome console. – Amadan Jul 24 '18 at 08:14