I see a lot of developer with a C# or Java background adopting JavaScript as well these days. Not that it should be a big surprise, lots of business applications are developed as client side browser based applications these days. And like it or not JavaScript is the language of the browser. Unfortunately the JavaScript syntax resembles that of Java or C# resulting in these developers thinking that they can easily master the language. And even though JavaScript is not a hard language to master there are some important differences and gotchas everyone needs to be aware of. So on these posts I am going to visit some of the things you just have to know. This time the scoping rules of JavaScript.
JavaScript scoping rules in the browser
JavaScript scoping rules in the browser are really very simple. There are just two scopes you can work with: global scope and function scope. Anything not defined in function scope is automatically global.
That seems simple enough but is very important and a lot of the structure of JavaScript is actually determined by this rule.
Seeing this in action is really simple. Suppose we take the following two scripts, each in its own JavaScript file:
1: var text = "Hello from script 1";
2:
3: setTimeout(function () {
4: console.log(text);
5: }, 1000);
1: var text = "Hello from script 2";
2:
3: setTimeout(function () {
4: console.log(text);
5: }, 1000);
Including these two scripts into an HTML page and loading then in the browser results in the following output:
The text variable of script 2 overwrites the variable from script 1 and we get the same message printed twice. Remember there is no file scope so both text variables are added to the global scope and the because they use the same name the second overwrites the first.
Fixing the problem with function scope
Fixing the problem basically means wrapping all the code in each file in a function. As we don’t actually need to reference the function anywhere else this is typically done with an Immediately-Invoked Function Expression (IIFE). See the code below:
1: (function() {
2: var text = "Hello from script 1";
3:
4: setTimeout(function () {
5: console.log(text);
6: }, 1000);
7: }());
1: (function() {
2: var text = "Hello from script 2";
3:
4: setTimeout(function () {
5: console.log(text);
6: }, 1000);
7: }());
Now the both text variables are scoped to the function they are contained in and no longer conflict. See the output below:
Conclusion
Wrapping all code in a JavaScript file in an IIFE is a simple little trick to make sure that everything has a private scope and nothing is leaked out unintentionally. All variables declared, and even more as we will see later, has function scope and this is a very important principal in JavaScript.
Enjoy!