Difference between variable declaration syntaxes in Javascript (including global variables)?
Yes, there are a couple of differences, though in practical terms they're not usually big ones.
There's a fourth way, and as of ES2015 (ES6) there's two more. I've added the fourth way at the end, but inserted the ES2015 ways after #1 (you'll see why), so we have:
var a = 0; // 1
let a = 0; // 1.1 (new with ES2015)
const a = 0; // 1.2 (new with ES2015)
a = 0; // 2
window.a = 0; // 3
this.a = 0; // 4
Those statements explained
#1 var a = 0;
This creates a global variable which is also a property of the global object, which we access as window
on browsers (or via this
a global scope, in non-strict code). Unlike some other properties, the property cannot be removed via delete
.
In specification terms, it creates an identifier binding on the object Environment Record for the global environment. That makes it a property of the global object because the global object is where identifier bindings for the global environment's object Environment Record are held. This is why the property is non-deletable: It's not just a simple property, it's an identifier binding.
The binding (variable) is defined before the first line of code runs (see "When var
happens" below).
Note that on IE8 and earlier, the property created on window
is not enumerable (doesn't show up in for..in
statements). In IE9, Chrome, Firefox, and Opera, it's enumerable.
#1.1 let a = 0;
This creates a global variable which is not a property of the global object. This is a new thing as of ES2015.
In specification terms, it creates an identifier binding on the declarative Environment Record for the global environment rather than the object Environment Record. The global environment is unique in having a split Environment Record, one for all the old stuff that goes on the global object (the object Environment Record) and another for all the new stuff (let
, const
, and the functions created by class
) that don't go on the global object.
The binding is created before any step-by-step code in its enclosing block is executed (in this case, before any global code runs), but it's not accessible in any way until the step-by-step execution reaches the let
statement. Once execution reaches the let
statement, the variable is accessible. (See "When let
and const
happen" below.)
#1.2 const a = 0;
Creates a global constant, which is not a property of the global object.
const
is exactly like let
except that you must provide an initializer (the = value
part), and you cannot change the value of the constant once it's created. Under the covers, it's exactly like let
but with a flag on the identifier binding saying its value cannot be changed. Using const
does three things for you:
- Makes it a parse-time error if you try to assign to the constant.
- Documents its unchanging nature for other programmers.
- Lets the JavaScript engine optimize on the basis that it won't change.
#2 a = 0;
This creates a property on the global object implicitly. As it's a normal property, you can delete it. I'd recommend not doing this, it can be unclear to anyone reading your code later. If you use ES5's strict mode, doing this (assigning to a non-existent variable) is an error. It's one of several reasons to use strict mode.
And interestingly, again on IE8 and earlier, the property created not enumerable (doesn't show up in for..in
statements). That's odd, particularly given #3 below.
#3 window.a = 0;
This creates a property on the global object explicitly, using the window
global that refers to the global object (on browsers; some non-browser environments have an equivalent global variable, such as global
on NodeJS). As it's a normal property, you can delete it.
This property is enumerable, on IE8 and earlier, and on every other browser I've tried.
#4 this.a = 0;
Exactly like #3, except we're referencing the global object through this
instead of the global window
. This won't work in strict mode, though, because in strict mode global code, this
doesn't have a reference to the global object (it has the value undefined
instead).
Deleting properties
What do I mean by "deleting" or "removing" a
? Exactly that: Removing the property (entirely) via the delete
keyword:
window.a = 0;
display("'a' in window? " + ('a' in window)); // displays "true"
delete window.a;
display("'a' in window? " + ('a' in window)); // displays "false"
delete
completely removes a property from an object. You can't do that with properties added to window
indirectly via var
, the delete
is either silently ignored or throws an exception (depending on the JavaScript implementation and whether you're in strict mode).
Warning: IE8 again (and presumably earlier, and IE9-IE11 in the broken "compatibility" mode): It won't let you delete properties of the window
object, even when you should be allowed to. Worse, it throws an exception when you try (try this experiment in IE8 and in other browsers). So when deleting from the window
object, you have to be defensive:
try {
delete window.prop;
}
catch (e) {
window.prop = undefined;
}
That tries to delete the property, and if an exception is thrown it does the next best thing and sets the property to undefined
.
This only applies to the window
object, and only (as far as I know) to IE8 and earlier (or IE9-IE11 in the broken "compatibility" mode). Other browsers are fine with deleting window
properties, subject to the rules above.
When var
happens
The variables defined via the var
statement are created before any step-by-step code in the execution context is run, and so the property exists well before the var
statement.
This can be confusing, so let's take a look:
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "undefined"
display("bar in window? " + ('bar' in window)); // displays "false"
display("window.bar = " + window.bar); // displays "undefined"
var foo = "f";
bar = "b";
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "f"
display("bar in window? " + ('bar' in window)); // displays "true"
display("window.bar = " + window.bar); // displays "b"
Live example:
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "undefined"
display("bar in window? " + ('bar' in window)); // displays "false"
display("window.bar = " + window.bar); // displays "undefined"
var foo = "f";
bar = "b";
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "f"
display("bar in window? " + ('bar' in window)); // displays "true"
display("window.bar = " + window.bar); // displays "b"
function display(msg) {
var p = document.createElement('p');
p.innerHTML = msg;
document.body.appendChild(p);
}
Difference between declaring variable
a = 5 will declare a global variable from any scope. var a = 5 will declare a variable within the declared scope.
a = 5; //global variable
var b = 6; // global variable
function foo(){
var c = 7; //local variable
d = 9; //global variable
}
Difference between function expression in global scope and function declaration
When you define a function without using var
statement, by default the function will be defined as a property in the global scope.
Quoting MDN documentation on var
,
Assigning a value to an undeclared variable implicitly creates it as a global variable (it becomes a property of the global object) when the assignment is executed. The differences between declared and undeclared variables are:
Declared variables are constrained in the execution context in which they are declared. Undeclared variables are always global.
Declared variables are created before any code is executed. Undeclared variables do not exist until the code assigning to them is executed.
Declared variables are a non-configurable property of their execution context (function or global). Undeclared variables are configurable (e.g. can be deleted).
Because of these three differences, failure to declare variables will very likely lead to unexpected results. Thus it is recommended to always declare variables, regardless of whether they are in a function or global scope. And in ECMAScript 5 strict mode, assigning to an undeclared variable throws an error.
So, when you define with function function_name(...){...}
syntax, it will be in the current scope.
Since the second function definition is in the global scope tr
's onclick can find f
. Try using var
statement like this
var f = function(){
alert('IT WORKS!!');
}
you will get the same ReferenceError: f is not defined
.
JavaScript global variable declaration syntax
Although both are properties of the global object, there is a difference: when you declare the variable with var
, its [[Configurable]]
internal attribute gets set to false
. Therefore, it's not possible to change its attributes with Object.defineProperty
(except for [[Value]]
). The most notable effect is that such variables cannot be delete
d:
var foo = 'bar';
window['bar'] = 'baz';
console.log(foo); // 'bar'
console.log(bar); // 'baz'
delete foo; // doesn't work, you can't delete vars
delete bar; // works, bar is an object property
console.log(foo); // 'bar'
console.log(bar); // ReferenceError
Also, when assigning a variable to a property, you make a COPY of the value instead of referencing the variable. This means external changes to the property don't affect the value of the variable.
(function() {
var foo = 'bar';
window['foo2'] = foo; //export foo
console.log(foo); // will output 'bar'
setTimeout(function() { console.log(foo) }, 1000); //will output 'bar'
})();
window['foo2'] = 'baz';
console.log(window['foo2']); // will output 'baz'
The above code will produce the following output:
'bar'
'baz'
'bar'
Is there any difference between a global variable and a property of the Global Object
Update, April 2020
As noted in the comments by D. Pardal, the first sentence below, written in 2012, is no longer always true in environments that support ES Modules (spec). Inside an ES module, a var
statement does not produce a property of the global object.
Original answer
A variable created using var
in the global scope does create a property of the global object. However, this property has different behaviour from a property of the global object that has not been created using var
.
Firstly, there is a difference in how a variable declaration is executed: a var
statement in the global scope creates a property of the global object before any code is executed, an effect commonly known as hoisting, well documented around the web (see references below).
Secondly, the global variable, unlike a property of the global object that has not been created with var
, cannot be deleted using the delete
operator (although this is not true in older versions of IE). delete
cannot be used to delete variables. This difference is down to internal property attributes that every object property has. These attributes are specified in the ECMAScript specification. In ECMAScript 5 terms, var foo = "bar"
creates a property foo
of the global object with the [[Configurable]]
attribute false
whereas this.foo = "bar"
(in global scope) creates a foo
property with [[Configurable]]
attribute true
.
References:
Dmitry Soshnikov has written at length about this in his excellent
series of articles, ECMAScript 262-3 in detail. I recommend
reading all of chapter 2, but the most relevant section is called
About Variables.The kangax article linked earlier contains a lot of
relevant information and details of browser bugs and deviations,
plus further quirks concerningwindow
.Angus Croll's Variables vs. Properties in JavaScript article, which links to many of the same resources as this answer.
The spec: ECMAScript 5.1.
difference between var keyword and without var
If var
keyword is used within a function or other non-global scope then that variable's scope is not global .
If var
keyword is not used before a variable name, then that variable's scope is global .
Define a global variable in a JavaScript function
As the others have said, you can use var
at global scope (outside of all functions and modules) to declare a global variable:
<script>
var yourGlobalVariable;
function foo() {
// ...
}
</script>
(Note that that's only true at global scope. If that code were in a module — <script type="module">...</script>
— it wouldn't be at global scope, so that wouldn't create a global.)
Alternatively:
In modern environments, you can assign to a property on the object that globalThis
refers to (globalThis
was added in ES2020):
<script>
function foo() {
globalThis.yourGlobalVariable = ...;
}
</script>
On browsers, you can do the same thing with the global called window
:
<script>
function foo() {
window.yourGlobalVariable = ...;
}
</script>
...because in browsers, all global variables global variables declared with var
are properties of the window
object. (In the latest specification, ECMAScript 2015, the new let
, const
, and class
statements at global scope create globals that aren't properties of the global object; a new concept in ES2015.)
(There's also the horror of implicit globals, but don't do it on purpose and do your best to avoid doing it by accident, perhaps by using ES5's "use strict"
.)
All that said: I'd avoid global variables if you possibly can (and you almost certainly can). As I mentioned, they end up being properties of window
, and window
is already plenty crowded enough what with all elements with an id
(and many with just a name
) being dumped in it (and regardless that upcoming specification, IE dumps just about anything with a name
on there).
Instead, in modern environments, use modules:
<script type="module">
let yourVariable = 42;
// ...
</script>
The top level code in a module is at module scope, not global scope, so that creates a variable that all of the code in that module can see, but that isn't global.
In obsolete environments without module support, wrap your code in a scoping function and use variables local to that scoping function, and make your other functions closures within it:
<script>
(function() { // Begin scoping function
var yourGlobalVariable; // Global to your code, invisible outside the scoping function
function foo() {
// ...
}
})(); // End scoping function
</script>
Related Topics
How to Check If File Exists in Jquery or Pure JavaScript
Correct Try...Catch Syntax Using Async/Await
Indexof Method in an Object Array
What Is the JavaScript ≫≫≫ Operator and How to Use It
Load Less.Js Rules Dynamically
How to Dynamically Modify <Select> in Materialize CSS Framework
Access CSS File Contents via JavaScript
Node.Js - How to Set Environment Variables in Code
Jquery Validate Plugin - How to Create a Simple Custom Rule
Why Does Chrome Debugger Think Closed Local Variable Is Undefined
How to Match a Whole Word in JavaScript
How to Replace All Line Breaks in a String With ≪Br /≫ Elements
How to Access a Dom Element in React? What Is the Equilvalent of Document.Getelementbyid() in React