1

I have read a couple of articles on the web explaining this in Javascript. While the articles have helped a lot, the behavior shown below is still unclear to me.

Here it says:

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

If so, can someone please explain the behavior (noted in the comments) when the following code is run with node.

console.log(this); // Returns an empty object: {}.
                  // Why does this line not return the global object.

var somefunc = function(name) {
    console.log(this);
}

somefunc(); // Returns the the global object. I think I understand this. The function is
           // invoked in a global context.

somefunc.call(this); // Again returns the empty object. Why?

Thanks for your help.

EDIT (as requested by below by the moderators) *How is this question and the chosen answer different from the one linked above*

I think both the question and certainly the answer here is clearer than the one that is considered a duplicate. The answer here clarifies what node is doing by giving example code, which is more helpful.

Curious2learn
  • 31,692
  • 43
  • 108
  • 125
  • This question has some interesting answers: http://stackoverflow.com/questions/3277182/how-to-get-the-global-object-in-javascript – Joe Jun 09 '13 at 18:56
  • 1
    Once the spelling is fixed, [I get the same result](http://jsbin.com/uyupal/1/edit) for all three variations. – Quentin Jun 09 '13 at 18:56
  • I get `[object Window]` three times: http://jsfiddle.net/GzNXk/. – Felix Kling Jun 09 '13 at 19:00
  • @Quentin The results are different even after fixing the spelling. – Curious2learn Jun 09 '13 at 19:00
  • I wouldn't worry about this. It's not a good idea to use `this` outside a method anyway (ES5 strict mode forbids it too) – Dave Jun 09 '13 at 19:01
  • I am running the code with NodeJS. Could the behavior be different in browser and in Node? Can you please check it with Node? – Curious2learn Jun 09 '13 at 19:01
  • @Curious2learn: If you're in a NodeJS module, then you're not in the global scope... rather your code is inside a function. For example, if you added `exports.foo = "bar";`, then you'll see that property and value on the local `this` as `this.foo; // "bar"`, but not on the global. –  Jun 09 '13 at 19:05
  • @CrazyTrain The above code is in a file called trial.js. There is nothing else in `trial.js` other than the above lines. I run it using `node trial.js` at the console. I am not very familiar with Node. I am using it mainly to run my javascript files in order to learn javascript. Regardless, it is still not clear why the behavior is different for the somefunc() and console.log(this). – Curious2learn Jun 09 '13 at 19:26
  • @Curious2learn: By loading it that way, you're effectively running it as a module. This means that your code in `trial.js` is grafted into a function body, so it's as though you wrapped all your code in a function, and then executed that function. In a module, you get a variable named `exports`, which is used to exporting data for that module. The value of `this` in a module also points to that same exports object. That's why you get `{}`, because to start with, the `exports` object is just an empty object. If you do `console.log(this === exports)`, you'll get `true`. –  Jun 09 '13 at 19:37
  • ...when you do `somefunc()`, you've not explicitly defined a `this` value, so it automatically gets the global object. When you do `somefunc.call(this)`, now you've defined it with the enclosing `this` value, which as I described above, is the `this` value that was defined for that invisible function. –  Jun 09 '13 at 19:40

1 Answers1

2

The first and the third showing of this should be identical in any case: in first case you just output the current value of this, and in the third you pass, again, the current value of this into somefunc (as a context argument).

But in the second, it's different: you call this function without assigning it any specific context, so this inside it points to a global object.

Why do you get an empty object as a result? One explanation is that your code is actually wrapped into some generic closure, like this:

var sandbox = {};
(function() {
  console.log(this);      // 1
  var somefunc = function(name) {
     console.log(this);
  }
  somefunc();             // 2
  somefunc.call(this);    // 3
}).call(sandbox);

As this function is called in sandbox context, both 1 and 3 point to sandbox - that is an empty object. 2 is different: you don't supply any context to this function call, that's why inside the function (when it's called that way) this points to global.

And that's exactly what happens when you try to access this in a global context of Node module. I'll quote an explanation from this discussion:

Node's modules are wrapped in a closure, which is evaluated in the this-context of the exports object. So, if you do var a = 3, then it won't be added to this, global, or exports. But, if you do this.a = 3 then it'll be added to this and exports.

See: https://gist.github.com/788414

Note that it's quite different from using the code as it is within a browser. It's not wrapped in any closure, so all the calls - 1, 2 and 3 - are referring to the global object. And that's, as you know, window.

raina77ow
  • 103,633
  • 15
  • 192
  • 229