1

Another topic on arrow functions and this value but I can't find the answer to the code that confuses me.

When I run this code in the browser's console the result is true:

var f = () => { return this; };
f() === window;                // true
f()                            // Window

But when I run the same code in Node I get different result:

var f = () => { return this; };
console.log(f() === global);    // false
console.log(f() === undefined); // false
console.log(f());               // {}

Also when an object is defined:

let button = {
    isClicked: false,
    click: () => { this.isClicked = true }
}

console.log(button.isClicked);   // false
button.click();
console.log(button.isClicked);   // false

When this line is executed in Node the result is undefined:

console.log(global.isClicked);   // undefined

But when executed in browser, the result is true:

console.log(window.isClicked);    // true

Why when the code is executed in the browser this refers to window object but when executed in Node this does not refer to global ?

Shubham Khatri
  • 211,155
  • 45
  • 305
  • 318
pollx
  • 433
  • 3
  • 14
  • 1
    [See this question.](http://stackoverflow.com/questions/22770299/meaning-of-this-in-node-js-modules-and-functions) In a Node module, at the outer level, `this` refers to `module.exports`. – Pointy Apr 28 '17 at 13:10

1 Answers1

2

But when I run the same code in Node I get different result:

Right. Code in Node is not run at global scope, it's run in a scope created for the Node "module" where this doesn't refer to the global object, it refers to the exports for the module (aka module.exports). More on Node modules here.

Also when an object is defined

this doesn't take on a different meaning within an object initializer. Your example code:

let button = {
    isClicked: false,
    click: () => { this.isClicked = true }
};

...is doing exactly what this code does:

let button = {
    isClicked: false
};
button.click = () => { this.isClicked = true };

In both cases, the click function closes over this as it is where we're creating button. this doesn't change meaning in the initializer, but that code assumes it does (specifically, the code assumes this becomes a reference to the object being created, which it doesn't; in fact, there's no way to refer to the object being created from within the initializer).

(The simplest solution in that particular case would be to use button instead of this, since the function also closes over button.)

Community
  • 1
  • 1
T.J. Crowder
  • 879,024
  • 165
  • 1,615
  • 1,639
  • Thanks for the answer! I just recalled module.exports is an empty object , so that explains the object literal I got as a result. But I find it confusing that ordinary functions' this refers to the global object and arrow functions' this refers to the module.exports object when AF is used as function expression. – pollx Apr 28 '17 at 13:43
  • @pollx: It's because arrow functions *close over* `this`. So if `this` refers to the exports object when you create an arrow function, `this` within the arrow function refers to the exports object. Closing over `this` (and `arguments` and `super`) instead of having their own versions of those is the key feature of arrow functions. In contrast, a non-arrow function gets its `this` set by how it's called, and in loose mode, if you call it directly (not via an object property or `.call` or similar), the `this` it gets is a reference to the global object. – T.J. Crowder Apr 28 '17 at 13:47
  • Thanks a lot ! What I'm missing actually is understanding of Node and its global objects (browser's as well): "Outside functions (in the top-level scope): _this_ refers to the global object in browsers and to a module’s exports in Node.js". Then "Arrow functions do not have their own _this_ value and they remember the value of the _this_ parameter at the time of their definition ". – pollx Apr 28 '17 at 15:00
  • Continues: The close over you say I understand as closure and since AF have _lexical this_ , that _this_ inherits module.exports. Then "In functions: _this_ is an extra, often implicit, parameter. In real functions, the value of _this_ depends on the mode one is in. Sloppy mode: _this_ refers to the global object (window in browsers)". Now in the button example it seems that I'm exporting 'isClicked' variable ... which is crazy. – pollx Apr 28 '17 at 15:00
  • @pollx: On a browser you would be, yes; and yes, it *is* crazy, which is part of why we have strict mode. Strict mode fixes some of the worst of the craziness of JavaScript, which (let's remember) was originally created in a period of 10 days in May 1995. Making `this` refer to the global object when you call a function directly was one of the biggest mistakes. Another (the biggest, in my view) was assigning to an undeclared identifier, which creates a global variable. Both are fixed in strict mode. – T.J. Crowder Apr 28 '17 at 15:35