JavaScript global variables and the global object

In javaScript global variables are variables that can be accessed from anywhere within the javaScript application and are therefor at the global name space. In most environments global variables are also part of what is often called the global object, in client side javaScfipt this is typically the window object but it can also be other objects as well such as when working with a web worker environment. In this post I will be writing about some things to be aware of when dealing with global variables, as well as the alternative when would be local function level, and not block level scoped variables.

1 - javaScript global basics

When a variable is defined at the top level which is outside of any function or code block using a keyword like var, let, or const that results in a global variable. There are also other ways of defining them as well by appending to the window object for example in client side javaScript, and it is even possible to define them by accident as well, such is the case with implicit globals.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
let global = 'a global';
(function () {
let notGlobal = 'not a global';
console.log(global); // 'a global'
console.log(notGlobal); // not a global
}
());
console.log(global); // 'a global'
try {
console.log(notGlobal);
} catch (e) {
console.log(e.message); // 'notGlobal is not defined'
}

The opposite of a global variable is often referred to as a local variable. Traditionally javaScript had function level local scope only, but now there is block level scope as well that can be used when using the let keyword in place of the traditional var keyword.

2 - Creating a global by appending to window in client side javaScript

It is possible to create globals in client side javaScript by just simply appending to the window object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<html>
<head>
<title>javascript globals with window</title>
</head>
<body>
<div></div>
<script>
let foo = function(){
window.bar = 'foobar';
};
foo();
document.getElementsByTagName('div')[0].innerText = bar;
</script>
</body>
</html>

The reason why this works is because in client side javaScript the window object is often the global object. At least in most cases it is. The situation changes when dealing with a web worker environment for example. It is also possible to define a global via the this keyword as well, but in some situations the this keyword may not always refer to the global object.

3 - Elements with ids are globals in client side javaScript

It is true that when an id attribute is assigned to an html element in client side javaScript a reference to that element becomes a global variable.

1
2
3
4
5
6
7
8
9
10
11
<html>
<head>
<title>ids are globals</title>
</head>
<body>
<div id="foo"></div>
<script>
foo.innerText='bar';
</script>
</body>
</html>

Something to watch out for, and this is also one of the reasons why javaScript developers get a little aggregated when defining globals. It is true that the global name space is all ready a little polluted event to begin with these days. However if you are sure that you are not over writing a global, or that there is no name space collisions of any kind, then defining a global now and then is no big deal when called for.

4 - Implicit Globals

It is possible to create what is often called an implicit global, this is something that often happens by accident by forgetting to use a keyword like var or let. Generally implicit globals are something that a javaScript developer would want to avoid doing. I can not think of any use case example in which doing so is called for. I would always want to declare my global variables at the top level. If for some reason I do want to create a global variable from within a function or block level scope there are other ways to do that such as appending to the window object in client side javaScript.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
let foo = function () {
// creating a local scoped x
let x = 40;
// creating y as an implicit global
y = 2;
return x + y;
};
console.log(foo()); // 42
try {
console.log(x); // will cause an error
} catch (e) {
console.log(e.message); // 'x is not defined'
}
// will return a value of 2 because I have
// created an implicit global
console.log(y); // 2

This might work as expected when it comes to the returned value, but it does result in two very different variables. One of which is coped locally within the function, and the other has become a global variable that can be accessed outside of the function. This can some times create problems if there is a situation in which there is a global variable of the same name all ready. In that case I would end up overwriting any value that that variable might have.