Avoiding global variables

Global variables can be accessed for reading or writing in any scope of an application. They are a necessary evil. Indeed, any application needs to organize its code structure in order to process input values and return the appropriate response or output. Problems and bugs start occurring when the code is not well organized and when any part of the code can therefore modify the global state of the rest of the application and modify the program's overall expected behavior.

Firstly, poorly organized code means that the scripting engine, or interpreter, has more work to do when trying to look up a variable name, because it will have to go through many scopes until it finds it in the global scope.

Secondly, poorly organized code means that the heap in memory will always be larger than needed to run the same functionality, since many superfluous variables will remain in memory until the end of the script's execution.

The solution to this problem is to avoid using global variables as much as possible and to use namespaced variables almost all the time. Also, using locally scoped variables has the added advantage of making sure that variables are automatically unset when the local scope is lost.

The following example (chap7_js_variables_1.html) shows us how the use of global variables can be very problematic and ultimately very inefficient, especially in increasing complex applications:

<!DOCTYPE html>

<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS Variables</title>

<meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body onload="myJS()" style="margin:0;">

<div id="main"></div>

<script type="text/javascript">

function Sum(n1, n2)
{
// These will be global when called from the myJSAgain() function.
this.number1 = Number(n1);
this.number2 = Number(n2);

return this.number1 + this.number2;
}

function myJS()
{
// Side-effect: creates a global variable named 'total'.
total = new Sum(3, 4);
alert( window.total ); // Object

// Side-effect: modifies the global variable named 'total'.
myJSAgain();

// Global 'total' variable got clobbered.
alert( window.total ); // 3
}

function myJSAgain()
{
// Missing 'new' keyword. Will clobber the global 'total' variable.
total = Sum(1, 2);

// There are now two sets of 'number1' and 'number2' variables!
alert( window.number2 ); // 2
}

</script>

</body>

</html>

The easy solution is to organize the code by using modules and namespaces. This is easily achieved by wrapping all variables and functions within a single application object in order to force a certain associated behavior when the variables are set or modified, and to preserve the application’s secrets from the global object. Closures can also be used to hide important values from the global scope. Let’s modify our previous script, keeping namespaces in mind this time:

function myJS()
{
function MyJSObject(n1, n2)
{
let number1 = Number(n1);
let number2 = Number(n2);

return {
set_number1: function (n1) {
number1 = Number(n1);
},
set_number2: function (n2) {
number2 = Number(n2);
},
sum: function ( ) {
return number1 + number2;
}
};
}

let oApp1 = new MyJSObject(3, 4);
alert( oApp1.sum() ); // 7

let app2 = MyJSObject(1, 2);
alert( app2.sum() ); // 3
alert( oApp1.sum() ); // 7
alert( window.number1 ); // undefined
}

By using the let keyword in this way, the developer would still obtain the correct value while avoiding to clobber a global variable and unintentionally modifying the global state of the entire application, even if he was to forget to use the new keyword. Furthermore, the global object remains lean and efficient by avoiding unnecessary bloat and by reducing time spent in namespace lookups in order to find a called function or a stored value.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset