Scope

Javascript scope

Variables in JavaScript are not defined in a block scope, but in a function scope. This means that if a variable is defined inside a function, it's not visible outside of the function. However, if it's defined inside an if or a for code block, it's visible outside the block. The term "global variables" describes variables you define outside of any function (in the global program code), as opposed to "local variables", which are defined inside a function. The code inside a function has access to all global variables as well as to its own local ones.

In example 1

  • The g()function has access to the myGlobal variable
  • Outside the g()function, the myLocal variable doesn't exist

Example 1

var myGlobal = 5;
function g() {
var myLocal = 7;
global++;
return myGlobal;
}

console.log(g()) //6
console.log(g()) //7
console.log(myLocal) //ReferenceError: myLocal is not defined
If you don't use var to declare a variable, this variable is automatically assigned a global scope. In example2
  • The function h()contains the variable myLocal. Before calling the function, the variable doesn't exist
  • When you call the function for the first time, the variable myLocal is created with a global scope. Then, if you access myLocal outside the function, it will be available.

Example 2


function h() {
myLocal = 7;
}

console.log(myLocal) //ReferenceError: myLocal is not defined
h(); //undefined
console.log(myLocal)//7

Best practice tips for variables

  • Minimize the number of global variables in order to avoid naming collisions. Imagine two people working on two different functions in the same script, and they both decide to use the same name for their global variable. This could easily lead to unexpected results and hard-to-find bugs.
  • Always declare your variables with the var statement.
  • Consider a "single var" pattern. Define all variables needed in your function at the very top of the function so you have a single place to look for variables and hopefully prevent accidental globals.

Example 3

To test where the various items are in scope we the following assertion method, named assert(). This method takes a value—an expression whose premise is asserted—and a description that describes the purpose of the assertion. If the value evaluates to true, and in other words is “truthy,” the assertion passes; otherwise it’s considered a failure. The associated message is logged with an appropriate pass/fail (red/green) indicator.
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>A test script</title></head>

<style>      
#results li.pass { color: green; }      
#results li.fail { color: red; }
</style>

<script>
    function assert(value, desc) {
      var li = document.createElement("li");
      li.className = value ? "pass" : "fail";
      li.appendChild(document.createTextNode(desc));
      document.getElementById("results").appendChild(li);
    }


//To test where the various items are in scope—and, perhaps more importantly, where they aren’t, we’ll intersperse a block of tests throughout this code. We’ll put the same block of tests, with one test for each of these declarations, at strategic places in the code. Each test asserts that one of the items we’re declaring is in scope (except for the first, which isn’t a test at all, but just a label that will help keep the code and output more readable). 
  
/*The testblock
assert(true,"-- BEFORE a --");
assert(typeof F==='function',"F() is in scope");
assert(typeof N==='function',"N() is in scope");
assert(typeof a==='string',"a is in scope");
assert(typeof b==='string',"b is in scope");
assert(typeof c==='string',"c is in scope");
*/ 


var a = "global variable";
var F = function () {
  var b = "local variable";
  var N = function () {}
  	var c = "inner local";
};

F();
 
</script> 

<body>
<ul id="results">

</ul>
</body>
</html>
scopes
Figure 1. Scopes of functions and variables

Check this example in your browser

Variable hoisting

Let's take a look at the next example that shows an important aspect of local versus global scoping: variable hoistin

var a = 677;
function f() {
console.log (a);// undefined
var a = 988;
console.log (a);//988
}
f();


You might expect that the first concole output will display 677 (the value of the globalvariable a) and the second will display 988 (the local variable a). But, this is not thecase. The first first concole output will show undefined. This is because inside the function the local scope is more important than the global scope. So, a local variable overwrites any global variable with the same name. At the time of the first concole output, the variable a was not yet defined (hence the value undefined), but it still existed in the local space due to the special behavior called hoisting.

When your JavaScript program execution enters a new function, all the variables declared anywhere in the function are moved (or elevated, or hoisted) to the top of the function. This is an important concept to keep in mind. Further, only the declaration is hoisted, meaning only the presence of the variable is moved to the top. Any assignments stay where they are. In the preceding example, the declaration of the local variable a was hoisted to the top. Only the declaration was hoisted, but not the assignment to 1. It's as if the function was written like this:

var a = 677;
function f() {
var a; // same as: var a = undefined;
console.log (a);// undefined
a = 988;
console.log (a);//988
}

You can also adopt the single var pattern mentioned previously in the best practice section. In this case, you'll be doing a sort of manual variable hoisting to prevent confusion with the JavaScript hoisting behavior

Leave a comment