Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OO Javascript : Definitive explanation of variable scope

Tags:

javascript

oop

Can someone provide an explanation of variable scope in JS as it applies to objects, functions and closures?

like image 493
javito Avatar asked Sep 19 '08 05:09

javito


People also ask

What is variable scope in JavaScript?

Variable Scope. Scope in JavaScript refers to the current context of code, which determines the accessibility of variables to JavaScript. The two types of scope are local and global: Global variables are those declared outside of a block. Local variables are those declared inside of a block.

What is JavaScript explain variable scope and assignment with example?

JavaScript has function scope: Each function creates a new scope. Variables defined inside a function are not accessible (visible) from outside the function. Variables declared with var , let and const are quite similar when declared inside a function. They all have Function Scope: function myFunction() {

Which two factors determine the scope of a variable in JavaScript?

The scope of a variable is controlled by the location of the variable declaration, and defines the part of the program where a particular variable is accessible. JavaScript has two scopes - global and local.

How does scope work in JavaScript?

In JavaScript, scopes are created by code blocks, functions, modules. While const and let variables are scoped by code blocks, functions or modules, var variables are scoped only by functions or modules. Scopes can be nested. Inside an inner scope you can access the variables of an outer scope.


2 Answers

Global variables

Every variable in Javascript is a named attribute of an object. For example:-

var x = 1;

x is added to the global object. The global object is provided by the script context and may already have a set of attributes. For example in a browser the global object is window. An equivalent to the above line in a browser would be:-

window.x = 1;

Local variables

Now what if we change this to:-

function fn()
{
    var x = 1;
}

When fn is called a new object is created called the execution context also referred to as the scope (I use these terms interchangeably). x is added as an attribute to this scope object. Hence each call to fn will get its own instance of a scope object and therefore its own instance of the x attribute attached to that scope object.

Closure

Now lets take this further:-

function fnSequence()
{
    var x = 1;
    return function() { return x++; }
}

var fn1 = fnSequence();
var fn2 = fnSequence();

WScript.Echo(fn1())
WScript.Echo(fn2())
WScript.Echo(fn1())
WScript.Echo(fn2())
WScript.Echo(fn1())
WScript.Echo(fn1())
WScript.Echo(fn2())
WScript.Echo(fn2())

Note: Replace WScript.Echo with whatever writes to stdout in your context.

The sequence you should get is :-

1 1 2 2 3 4 3 4

So what has happened here? We have fnSequence which initialises a variable x to 1 and returns an anonymous function which will return the value of x and then increment it.

When this function is first executed a scope object is created and an attribute x is added to that scope object with the value of 1. Also created in the same execution object is an anonymous function. Each function object will have a scope attribute which points to the execution context in which it is created. This creates what is know as a scope chain which we will come to later. A reference to this function is returned by fnSequence and stored in fn1.

Note that fn1 is now pointing at the anonymous function and that the anonymous function has a scope attribute pointing at a scope object that still has an x attribute attached. This is known as closure where the contents of an execution context is still reachable after the function it was created for has completed execution.

Now this same sequence happens when assigning to fn2. fn2 will be pointing at a different anonymous function that was created in a different execution context that was create when fnSequence was called this second time.

Scope Chain

What happens when the function held by fn1 is executed the first time? A new execution context is created for the execution of the anonymous function. A return value is to be found from the identifier x. The function's scope object is inspected for an x attribute but none is found. This is where the scope chain comes in. Having failed to find x in the current execution context JavaScript takes the object held by the function's scope attribute and looks for x there. It finds it since the functions scope was created inside an execution of fnSequence, retrieves its value and increments it. Hence 1 is output and the x in this scope is incremented to 2.

Now when fn2 is executed it is ultimately attached to a different execution context whose x attribute is still 1. Hence executing fn2 also results in 1.

As you can see fn1 and fn2 each generate their own independent sequence of numbers.

like image 160
AnthonyWJones Avatar answered Oct 05 '22 00:10

AnthonyWJones


Variables not declared with var are global in scope. Functions introduce a scope, but note that if blocks and other blocks do not introduce a scope.

I could also see much information about this by Googling Javascript scope. That's really what I would recommend. http://www.digital-web.com/articles/scope_in_javascript/

like image 28
moltenform Avatar answered Oct 04 '22 23:10

moltenform