Global Variable NOT working - Node 14.15.3 - javascript

var myVariable = 3;
console.log('global', globalThis.myVariable);
I tried running the code using node file.js, but keep getting the result:
global undefined
Can someone explain to me what exactly is going on here?

I find this from Node documentation:
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.
and Global object:
In JavaScript, there's always a global object defined. In a web browser, when scripts create global variables defined with the var keyword, they're created as members of the global object. (In Node.js this is not the case.)
It mean that when you declare var myVariable = 3; it doesn't go into the node global object, you can try to print global object out.

Try to assign value to globalThis variable
globalThis.myVariable = 3;
console.log('global', globalThis.myVariable);

In Node Js scoping, any variable declared in the root of a module (a particular JS file) is a module-level variable.
var test = 'This string is global to this module';
function foo() {
console.log(test);
}
Node Js also has the Global Namespace Object.
This object is accessible in any module.
global.test = 'This string iscan be accessed by any module via the gloabl namespace object';
function foo() {
console.log(global.test);
}

var global.myVariable = 3;
console.log('myVariable')
I did not check the code though

Related

Scope of a let variable JavaScript [duplicate]

In JavaScript, var declarations create properties on the global object:
var x = 15;
console.log(window.x); // logs 15 in browser
console.log(global.x); // logs 15 in Node.js
ES6 introduces lexical scoping with let declarations that have block scope.
let x = 15;
{
let x = 14;
}
console.log(x); // logs 15;
However, do these declarations create properties on the global object?
let x = 15;
// what is this supposed to log in the browser according to ES6?
console.log(window.x); // 15 in Firefox
console.log(global.x); // undefined in Node.js with flag
Do let statements create properties on the global object?
According to the spec, no:
A global environment record is logically a single record but it is specified as a composite encapsulating an object environment record and a declarative environment record. The object environment record has as its base object the global object of the associated Realm. This global object is the value returned by the global environment record’s GetThisBinding concrete method. The object environment record component of a global environment record contains the bindings for all built-in globals (clause 18) and all bindings introduced by a FunctionDeclaration, GeneratorDeclaration, or VariableStatement contained in global code. The bindings for all other ECMAScript declarations in global code are contained in the declarative environment record component of the global environment record.
Some more explanation:
A declarative environment record stores the bindings in an internal data structure. It's impossible to get a hold of that data structure in any way (think about function scope).
An object environment record uses an actual JS object as data structure. Every property of the object becomes a binding and vice versa. The global environment has an object environment object whose "binding object" is the global object. Another example is with.
Now, as the cited part states, only FunctionDeclarations, GeneratorDeclarations, and VariableStatements create bindings in the global environment's object environment record. I.e. only this bindings become properties of the global object.
All other declarations (e.g. const and let) are stored in the global environment's declarative environment record, which is not based on the global object.
Standard scripts:
Both let and var variables, if declared at the top-level of a script, are accessible outside of the script file. However, only var variables get assigned to the window object. Have a look at this code snippet as proof:
<script>
var namedWithVar = "with var";
let namedWithLet = "with let";
</script>
<script>
console.log("Accessed directly:");
console.log(namedWithVar); // prints: with var
console.log(namedWithLet); // prints: with let
console.log("");
console.log("Accessed through window:");
console.log(window.namedWithVar); // prints: with var
console.log(window.namedWithLet); // prints: undefined
</script>
Javascipt modules:
Note that modules are a different story. Variables declared in a module are not made available in the global scope:
<script type="module">
var namedWithVar = "with var";
let namedWithLet = "with let";
</script>
<script>
console.log(namedWithVar); // ReferenceError
</script>
<script>
console.log(namedWithLet); // ReferenceError
</script>
<script>
console.log(window.namedWithVar); // prints: undefined
console.log(window.namedWithLet); // prints: undefined
</script>
Per the specification:
"let and const declarations define variables that are scoped to the running execution context’s LexicalEnvironment."
This means that you should be able to access the variable inside the execution scope, but not outside. This expands the execution scope beyond the classic JS closure structure of function-only or global.
Defining a let variable globally should not expose the variable on the global context, as used to be the case in Firefox. In practice you should not define variables in a global context.
Variables declared via let keyword do not create accessible properties on a global object (window for a browser).
Actually, Firefox fixed its behavior: let v = 42; 'v' in window // false
let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. This is unlike the var keyword, which defines a variable globally, or locally to an entire function regardless of block scope.
At the top level of programs and functions, let, unlike var, does not create a property on the global object. For example:
var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined
The scope of a variable declared with var is its current execution context, which is either the enclosing function or, for variables declared outside any function, global. If you re-declare a JavaScript variable, it will not lose its value. For example:
var x = 1;
if (x === 1) {
var x = 2;
console.log(x);
// output: 2
}
console.log(x);
// output: 2
Note: that unlike C, C++, and Java, JavaScript does not have block-level scope when you declare a variable using var.
As we mentioned before let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. For example:
let x = 1;
if (x === 1) {
let x = 2;
console.log(x);
// output: 2
}
console.log(x);
// output: 1
Here I recommend you to read about Variable Scope

Do let statements create properties on the global object?

In JavaScript, var declarations create properties on the global object:
var x = 15;
console.log(window.x); // logs 15 in browser
console.log(global.x); // logs 15 in Node.js
ES6 introduces lexical scoping with let declarations that have block scope.
let x = 15;
{
let x = 14;
}
console.log(x); // logs 15;
However, do these declarations create properties on the global object?
let x = 15;
// what is this supposed to log in the browser according to ES6?
console.log(window.x); // 15 in Firefox
console.log(global.x); // undefined in Node.js with flag
Do let statements create properties on the global object?
According to the spec, no:
A global environment record is logically a single record but it is specified as a composite encapsulating an object environment record and a declarative environment record. The object environment record has as its base object the global object of the associated Realm. This global object is the value returned by the global environment record’s GetThisBinding concrete method. The object environment record component of a global environment record contains the bindings for all built-in globals (clause 18) and all bindings introduced by a FunctionDeclaration, GeneratorDeclaration, or VariableStatement contained in global code. The bindings for all other ECMAScript declarations in global code are contained in the declarative environment record component of the global environment record.
Some more explanation:
A declarative environment record stores the bindings in an internal data structure. It's impossible to get a hold of that data structure in any way (think about function scope).
An object environment record uses an actual JS object as data structure. Every property of the object becomes a binding and vice versa. The global environment has an object environment object whose "binding object" is the global object. Another example is with.
Now, as the cited part states, only FunctionDeclarations, GeneratorDeclarations, and VariableStatements create bindings in the global environment's object environment record. I.e. only this bindings become properties of the global object.
All other declarations (e.g. const and let) are stored in the global environment's declarative environment record, which is not based on the global object.
Standard scripts:
Both let and var variables, if declared at the top-level of a script, are accessible outside of the script file. However, only var variables get assigned to the window object. Have a look at this code snippet as proof:
<script>
var namedWithVar = "with var";
let namedWithLet = "with let";
</script>
<script>
console.log("Accessed directly:");
console.log(namedWithVar); // prints: with var
console.log(namedWithLet); // prints: with let
console.log("");
console.log("Accessed through window:");
console.log(window.namedWithVar); // prints: with var
console.log(window.namedWithLet); // prints: undefined
</script>
Javascipt modules:
Note that modules are a different story. Variables declared in a module are not made available in the global scope:
<script type="module">
var namedWithVar = "with var";
let namedWithLet = "with let";
</script>
<script>
console.log(namedWithVar); // ReferenceError
</script>
<script>
console.log(namedWithLet); // ReferenceError
</script>
<script>
console.log(window.namedWithVar); // prints: undefined
console.log(window.namedWithLet); // prints: undefined
</script>
Per the specification:
"let and const declarations define variables that are scoped to the running execution context’s LexicalEnvironment."
This means that you should be able to access the variable inside the execution scope, but not outside. This expands the execution scope beyond the classic JS closure structure of function-only or global.
Defining a let variable globally should not expose the variable on the global context, as used to be the case in Firefox. In practice you should not define variables in a global context.
Variables declared via let keyword do not create accessible properties on a global object (window for a browser).
Actually, Firefox fixed its behavior: let v = 42; 'v' in window // false
let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. This is unlike the var keyword, which defines a variable globally, or locally to an entire function regardless of block scope.
At the top level of programs and functions, let, unlike var, does not create a property on the global object. For example:
var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined
The scope of a variable declared with var is its current execution context, which is either the enclosing function or, for variables declared outside any function, global. If you re-declare a JavaScript variable, it will not lose its value. For example:
var x = 1;
if (x === 1) {
var x = 2;
console.log(x);
// output: 2
}
console.log(x);
// output: 2
Note: that unlike C, C++, and Java, JavaScript does not have block-level scope when you declare a variable using var.
As we mentioned before let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. For example:
let x = 1;
if (x === 1) {
let x = 2;
console.log(x);
// output: 2
}
console.log(x);
// output: 1
Here I recommend you to read about Variable Scope

How can I dynamically access a global variable in Node?

In browser-based JavaScript, you can do something like this:
var foo = "foo";
(function() {
var foo = "bar";
console.log(foo);
// => "bar"
console.log(window["foo"]);
// => "foo"
})();
Is there any way to do something similar in Node, which lacks a window object?
If you want an environment agnostic approach, for example, when writing code to work on both the browser and Node.js, you can do something like this in global code at the top of your JavaScript file:
var globalObject = typeof global === "undefined" ? this : global;
and then use globalObject similar to how you would window in the browser context and as you would use global in the Node.js context.
Note that you must declare a variable without var for it to be part of the global object in Node.js.
You can access global variables using global keyword in nodejs.
Note:- There is one rule in nodejs only those variables willl be global variables which dose not have declared using var.
Like if you have declareation like bellow
foo = "sample"; //this you can access using global
But
var foo = "sample"; //this you cann't access using global.
The second one is not actually in global scope, it's local to that module.
From node global docs
In browsers, the top-level scope is the global scope. That means that
in browsers if you're in the global scope var something will define a
global variable. In Node this is different. The top-level scope is not
the global scope; var something inside a Node module will be local to
that module.

Does node.js have equivalent to window object in browser

What I mean is does node.js have object that are global function methods of. Like this in browser:
function myGlobalFunction() {
console.log(this === window);
}
myGlobalFunction();
=> true
The closest equivalent in node is global. I'm not sure if it translates in all of the same ways, but if you open a REPL and type in this === global, it will return true.
Here's a discussion on the global object, though some it the information may be deprecated as it's pretty old: 'Global' object in node.js
Yes, the global variable is the global object in Node.js
From the docs:
global# {Object} The global namespace object. In browsers, the
top-level scope is the global scope. That means that in browsers if
you're in the global scope var something will define a global
variable. In Node this is different. The top-level scope is not the
global scope; var something inside a Node module will be local to that
module.

Ways to break JavaScript Scope

JavaScript normally follows the function scope i.e. variables are accessible only within the function in which they are declared.
One of the ways to break this convention and make the variable accessible outside the function scope is to use the global window object
e.g.
window.myVar = 123;
My question is are there any other ways in JavaScript/jQuery to make the variable accessible outside the function scope?
Not with variable declarations, no. You can obviously declare a variable in an outer scope so that it's accessible to all descendant scopes:
var a; // Available globally
function example() {
a = "hello"; // References a in outer scope
}
If you're not in strict mode you can simply remove the var keyword. This is equivalent to your example:
// a has not been declared in an ancestor scope
function example() {
a = "hello"; // a is now a property of the global object
}
But this is very bad practice. It will throw a reference error if the function runs in strict mode:
function example() {
"use strict";
a = "hello"; // ReferenceError: a is not defined
}
As you wrote, variables are only visible inside the function in which they were defined (unless they are global).
What you can do is assign variables to the function object itself:
function foo() {
foo.myVar = 42;
}
console.log(foo.myVar); // outputs "undefined"
foo();
console.log(foo.myVar); // outputs "42"
But I would advise against it. You should really have a very good reason to do something like this.
You can define them as part of a global object, then add variables later
// Define your global object
var myObj = {};
// Add property (variable) to it
myObj.myVar = 'Hello world';
// Add method to it
myObj.myFunctions = function() {
// Do cool stuff
};
See the link below:
Variable declaration
Also, you can declare it without the var keyword. However, this may not be a good practice as it pollutes the global namespace. (Make sure strict mode is not on).
Edit:
I didn't see the other comments before posting. #JamesAllardice answer is also good.

Categories