I'm reading the "You don't know JS" book series and I tried to run the snippet:
function foo() {
console.log( this.a );
}
function doFoo(fn) {
// `fn` is just another reference to `foo`
fn(); // <-- call-site!
}
var obj = {
a: 2,
foo: foo
};
var a = "oops, global"; // `a` also property on global object
doFoo( obj.foo ); // "oops, global"
(You can find it in the 2nd chapter of the 3d book: 'this' All make sense now)
If I save this into 'foo.js' and run it with node foo.js (v 8.11.1) then I get undefined. While if I start node REPL and type in the same code I get:
> function foo() { console.log(this.a); }
undefined
> function doFoo(fn) { fn(); }
undefined
> var obj = { a:2, foo:foo };
undefined
> var a = "oops, global";
undefined
> doFoo(obj.foo);
oops, global
undefined
As expected from the book. Same result on Firefox dev console.
If I remove the declaration and leave only the assignment a = "oops, global" then it run as expected both on REPL and Node.js. This make more sense to me because in this way I'm setting a property on the global object, while in the "original" way I'm just declaring a variable.
Can anyone explain to me this behaviour? Thank you all.
EDIT: I think I'm close to the solution, I noticed that if I make a script foo.js that contains only:
var x = 42;
console.log(this);
I get {}, so x is not attached to the global object. While if I start the Node.js REPL and type in the same code I get a big object with x attached to it:
{
...
x: 42
}
So I think the difference it depends on "who is the global object?" in REPL and in Node.js.
When you run the file in Node.js, your
var aisn't actually in global scope, but function scope -- a module function scope (more on this here). Basically all of the contents of the file is run as if inside a function. Sovar ais actually in that function scope.Whereas in REPL it's truly in global scope.