0
var name = "Global";

function funcA() {
    var name = "FunA";
    return function() {
        console.log(this.name);
    }
}

funcA()();

I run the code above on my terminal using node and return undefined but in chrome console it will return Global.

Why is this happened?

dhilt
  • 18,707
  • 8
  • 70
  • 85
Dreams
  • 8,288
  • 10
  • 45
  • 71
  • sorry, just edit the code and it will print Global then undefined, why? – Dreams Nov 02 '17 at 17:07
  • I see the log message `Global` followed by the return value `undefined` in both Node (admitted ancient 0.12.4) and Chrome. Can you show a screenshot of what Node does? In **no** environment does `funcA()()` have a return value (other than the default `undefined` due an absence of a `return`ed value). `function() { console.log(this.name); }` has zero `return` statements inside it. – apsillers Nov 02 '17 at 17:13
  • Also, beware [the danger of using a global variable called `name`](https://stackoverflow.com/q/10523701/710446), which will be stringified in browser code. (Not a problem here, since it is a string, but may cause trouble for other types.) – apsillers Nov 02 '17 at 17:20
  • 2
    Are you running this code as a module? (Top-level variables in modules are not global, which would explain why you see different values logged.) – apsillers Nov 02 '17 at 17:28
  • 1
    @apsillers I believe he runs it via `node test.js`... – dhilt Nov 02 '17 at 17:47

2 Answers2

2

1. Running this script in Browser environment forces that top-level var to become a property of the global window object. Then per MDN:

Since the following code is not in strict mode, and because the value of this is not set by the call, this will default to the global object , which is window in a browser.

So calling console.log(this.name); inside that function means that this would be a link to the global window object, which would have name property. And the value of window.name is "Global".

2. NodeJS has no window object, but it has global object instead. Running script in NodeJS environment breaks on two situations: (a) running as module (e.g. via node test.js) and (b) running not as module (e.g. directly in node console). The second case (b) works the same as for Browser: global would receive name property and this would be a link to global, so the value of this.name would be equal to global.name and would be "Global".

But first case (a) is different, per NodeJS doc:

Object The global namespace object.

In browsers, the top-level scope is the global scope. This means that within the browser var something will define a new global variable. In Node.js this is different. The top-level scope is not the global scope; var something inside a Node.js module will be local to that module.

So that top-level var becomes just a local variable in the Node environment, and since global has no name property, calling console.log(this.name) shows undefined.

dhilt
  • 18,707
  • 8
  • 70
  • 85
  • 1
    but is node doesn't have global object? – Dreams Nov 02 '17 at 17:15
  • So, my understanding is this answer implicitly suggests that the OP's code is running inside of a module so that the top-level `var name = "Global";` does not create a global variable, correct? Indeed, that would explain it, if true, though I think you should make that assumption more explicit. – apsillers Nov 02 '17 at 17:24
  • @apsillers If you define `global.name = "Global";` instead of `var name = "Global"`, it will work. – dhilt Nov 02 '17 at 17:27
  • @Dreams: It does. Every JavaScript environment has a global object. It's not standardized which global variables exist by default though. – Felix Kling Nov 02 '17 at 17:32
  • @apsillers Variables declared via `var` do not become `global` object properties in Node, as they do for `window` in Browser. – dhilt Nov 02 '17 at 18:00
  • @dhilt It's not correct. I've tested it on Node v9.0.0 right now – SerG Nov 02 '17 at 18:08
  • @SerG The issue here is that global variables *do* become properties of `global` *within the REPL*, but do not when code is run as a "module".The confusing distinction here is that direct execution of a file (`node foo.js`) is "modular" execution. Indeed, running the OP's file as `node test.js` does not add a property to `global` whereas running it in the console *does* add a `global` property. – apsillers Nov 02 '17 at 18:12
  • @apsillers That's exactly what I mean in my answer. – SerG Nov 02 '17 at 18:14
  • @dhilt: They probably are if they are defined in global scope. But you are usually working with modules (and thus module scope) in Node. – Felix Kling Nov 02 '17 at 19:07
0

var in top level scope defines variable in Global object.

this in your anonymous function call is pointed to Global object in case of browser or interactive Node session but to exports-object in case of script running as node module.

It's until strict mode...

SerG
  • 1,251
  • 4
  • 18
  • 37