2

I'm learning how to change the context of the function in Javascript from this slide. Here the example given is perfectly understandable:

var object = {}; 
function fn(){ 
  return this; 
} 
console.log( fn() == this) //true
console.log( fn.call(object) == object); //true

But when I try this in Node JS, the result is somewhat different. First statement results in false and second equality is working as expected. So is there any difference in Global scope of Node JS and browser?

I know that browser has Global scope named window, but what about Node JS? What is the difference between those scopes which leads to the above different behaviours?

Kaushal28
  • 4,823
  • 4
  • 30
  • 57
  • `fn() == this` is evaluating to `true` for me in Node 8.9.3 (note, good to prefer strict equality to sloppy equality) – CertainPerformance Dec 01 '18 at 11:01
  • @CertainPerformance See this: http://tpcg.io/EJZeya. This is giving same result as my local Node JS. But in browser, both statements evaluates to `true`. My Node Version in 8.11.2 – Kaushal28 Dec 01 '18 at 11:03
  • Ah, I was typing into the REPL directly, rather than running a `.js`, that must be the reason for the difference. – CertainPerformance Dec 01 '18 at 11:14
  • You should always use strict mode and expect `fn() == undefined`. – Bergi Dec 01 '18 at 13:59

1 Answers1

1

So is there any difference in Global scope of Node JS and browser?

The difference is that the script isn't evaluated in global scope in Node, it's evaluated in module scope where this isn't global variable when it's evaluated directly.

In browser, it is this === window. In Node.js, it is this === module.exports.

If fn was an arrow, it would be this === module.exports in Node.js there. But since it's regular function, it's evaluated in global scope when called like fn().

Estus Flask
  • 150,909
  • 47
  • 291
  • 441
  • Then the `this` returned from function `fn` also should be `module.exports` and so 1st statement should evaluate to `true` – Kaushal28 Dec 01 '18 at 11:15
  • That's what *evaluated directly* refers to. Since `fn` isn't an arrow, it doesn't get `this` from enclosing context (module scope) and is evaluated in global scope. It's same as `eval('this')===module.exports` and `(0, eval)('this')===global`. – Estus Flask Dec 01 '18 at 11:18
  • Oh! When I changed it to arrow function, the first returned `true` and second returned `false`! There is too much I don't know about the arrow vs regular functions in JS. – Kaushal28 Dec 01 '18 at 11:22
  • Arrow functions always get lexical `this`, they ignore a context that is passed with `call`, `apply` or `bind` to them. Consider checking https://stackoverflow.com/questions/34361379/arrow-function-vs-function-declaration-expressions-are-they-equivalent-exch – Estus Flask Dec 01 '18 at 11:27
  • That is great! I learned many thing today. Thanks. – Kaushal28 Dec 01 '18 at 11:42
  • @estus "*`fn()` is evaluated in global scope*" - actually, `fn` is called with `undefined` for the `this` argument, and only because it is (not an arrow function and) a **sloppy mode** function the value changes to the global object. – Bergi Dec 01 '18 at 14:03