Difference Between Variable Declaration Syntaxes in JavaScript (Including Global Variables)

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:

  1. Makes it a parse-time error if you try to assign to the constant.
  2. Documents its unchanging nature for other programmers.
  3. 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:

  1. Declared variables are constrained in the execution context in which they are declared. Undeclared variables are always global.

  2. Declared variables are created before any code is executed. Undeclared variables do not exist until the code assigning to them is executed.

  3. 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 deleted:

​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 concerning window.

  • 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



Leave a reply



Submit