Javascript - understanding the scope chain's reference priority - javascript

I would like to better understand the scope chain the hopefully closure better and so the following code:
function greet(whattosay){
return function(name) {
whattosay = "not hi"; //change the hi message
console.log(whattosay + ' ' + name);
function insideAnon() {
console.log(whattosay);
}
}
}
var sayHi = greet('Hi'); //get in return the anon function
sayHi("John"); //print not hi John on the console
I have recently learned that every "variable environment" is actually an array or an object with properties, and so each function has a reference to it's parent's function variable environment object/array. But my question is, what exactly is the scope chain?(I know that it is supposedly going "down" up until the global level), My current perception (Not sure) is that each child has it's parent and grandparent (and so on) variable environment references inside of it, and so it first check it's parent's variable environment object, if a variable is not there it looks at it's grandparent's reference and so on. Or is it more like - Check the parent variable environment object reference, if not there that parent checks his parent's reference and so on. I HOPE i was very clear at what I was trying to say - How it really goes down the "chain".

You can get references about scope chains from this question:
Scope Chain in Javascript

Each function creates a scope object that contains the arguments for that function and the local variables defined in that function.
Since Javascript uses lexical scoping, that means that a given piece of code can access variables defined within the current function or within any parent function. Javascript makes this work by maintaining a chain of scope objects so each scope has a reference to its parent scope.
When a given piece of code accesses a variable like:
foo = 1;
Javascript, looks in the current scope object to see if something named foo exists there. If so, that variable is used. If not, it gets the reference to the parent scope, checks that scope for something named foo and continues this process up the parent chain until it gets to the global scope and thus can go no further.
So, in this example:
function one() {
var foo = 2;
function two() {
var fee = 3;
function three() {
foo = 1;
}
three();
}
two();
}
one();
The function one() will execute and define foo and two in its scope. It will then call two() which will execute and define fee and three in its scope. It will then call three() which will execute and attempt to change the value of foo. It will first look in the scope object belonging to three, but it will not find anything named foo there so it will go to the parent scope of three which will be the two scope object. It will not find a variable named foo in that scope object so it will go to the parent object of two which will be the scope object of one. There it will find a variable named foo so it will change the value of that variable.
On thing that is different about Javascript scope objects compared to something like a C++ stack frame is that they can continue to live after the function that created them has finished executing. This is a very common structure in Javascript and is often referred to as a closure. Here's a simple example of that:
function initializeCntr() {
var cntr = 0;
document.getElementById("test").addEventListener("click", function(e) {
++cntr;
document.getElementById("clickCnt").innerHTML = cntr;
});
}
initializeCntr();
In this short code example, there are three scopes present, the global scope (that contains the initializeCntr symbol), the initializeCntr scope that contains the cntr variable and the scope that belongs to the anonymous function that is set as the event handler.
When you call initializeCntr(), it creates a function scope object that contains the variable cntr. It then runs the addEventListener() method and passes a reference to the inline anonymous event handler for addEventListener(). The initializeCntr() method then finishes execution. But, because the inline anonymous function passed as the event handler contains a reference to the cntr variable in the initializeCntr scope object, that scope object is NOT garbage collected even though initializeCntr() has finished executing. Instead, it is kept alive because of the lasting reference to the cntr variable in it. When that click event handler is then called sometime in the future, it can use that cntr variable. In fact, the initalizeCntr scope will be kept alive as long as the event handler is active. If the event handler is removed or the DOM object it is attached to is removed, then and only then would the initializeCntr scope object be eligible for garbage collection and eventually get freed.
Some JS implementations are smart enough to not necessarily retain the entire scope object and everything in it, but instead to only retain the elements of the scope object that are specifically referenced in child scopes that are still active. So, if there were other variables next to cntr that were not used in the event handler, those other variables could be freed.
FYI, this longer lasting scope is called a closure. Closures are very useful concepts in Javascript and something not available in a language like C++ (because they rely on garbage collection).

Related

Will a function defined within a function as a sibling have access to its sibling local variables?

I recently took a technical interview and one of the questions dealt with scope issues.
var test = {
constructor : function() {
var x="";
test[sibling] = function() {
console.log(x);
}
}
};
test.constructor();
test.sibling();
When a function runs, will it test anonymously declared functions for dependencies? And when test.sibling() is initialized, will it reinitialize test.constructor()? If not, are there ways to have a function test nested anonymous functions for dependencies without initializing it?
That code won't even run. When test.constructor(); is invoked, test[sibling] =... is encountered, the JS engine will attempt to resolve what the sibling variable evaluates to, however sibling is not defined anywhere and an error is thrown.
But, to your specific question about how variables are resolved. It can be easy to understand, provided you understand lexical scope. In a nutshell, think of a function as a "bubble". Functions can be nested inside other functions, which creates bubbles inside of other bubbles. A function always has access to its own variables and the variables of its parent bubbles, but not sibling bubbles.
Whenever a function is nested inside another, a closure is formed. The child function "closes" around the parent's variables. The real trick is what happens when a child bubble (function) persists longer than its parent function. Normally, a function's variables are garbage collected when the function completes, but if, during the course of the parent function executing, a child function is defined and somehow returned from the parent (via a return statement or by assignment as a callback to another object, etc.), the child function will need those parent function variables at some future point in time, meaning that the parent's variables won't be garbage collected when the parent function completes. This is the nature of closures.

Is a function return necessary to be called a Closure

Hey i came across this video on youtube http://www.youtube.com/watch?v=KRm-h6vcpxs
which basically explains IIFEs and closures. But what I am not understanding is whether i need to return a function in order to call it a closure.
E.x.
function a() {
var i = 10;
function b() {
alert(i);
}
}
in this case can i call it a closure as it is accessing the 'i' variable from the outer function's scope or do i need to return the function like this
return function b(){alert(i);}
A closure is simply a function which holds its lexical environment and doesn't let it go until it itself dies.
Think of a closure as Uncle Scrooge:
Uncle Scrooge is a miser. He will never let go of his money.
Similarly a closure is also a miser. It will not let go of its variables until it dies itself.
For example:
function getCounter() {
var count = 0;
return function counter() {
return ++count;
};
}
var counter = getCounter();
See that function counter? The one returned by the getCounter function? That function is a miser. It will not let go of the count variable even though the count variable belongs to the getCounter function call and that function call has ended. Hence we call counter a closure.
See every function call may create variables. For example a call to the getCounter function creates a variable count. Now this variable count usually dies when the getCounter function ends.
However the counter function (which can access the count variable) doesn't allow it to die when the call to getCounter ends. This is because the counter function needs count. Hence it will only allow count to die after it dies itself.
Now the really interesting thing to notice here is that counter is born inside the call to getCounter. Hence even counter should die when the call to getCounter ends - but it doesn't. It lives on even after the call to getCounter ends because it escapes the scope (lifetime) of getCounter.
There are many ways in which counter can escape the scope of getCounter. The most common way is for getCounter to simply return counter. However there are many more ways. For example:
var counter;
function setCounter() {
var count = 0;
counter = function counter() {
return ++count;
};
}
setCounter();
Here the sister function of getCounter (which is aptly called setCounter) assigns a new counter function to the global counter variable. Hence the inner counter function escapes the scope of setCounter to become a closure.
Actually in JavaScript every function is a closure. However we don't realize this until we deal with functions which escape the scope of a parent function and keep some variable belonging to the parent function alive even after the call to the parent function ends.
For more information read this answer: https://stackoverflow.com/a/12931785/783743
Returning the function changes nothing, what's important is creating it and calling it. That makes the closure, that is a link from the internal function to the scope where it was created (you can see it, in practice, as a pointer. It has the same effect of preventing the garbaging of the outer scope, for example).
By definition of closure, the link from the function to its containing scope is enough. So basically creating the function makes it a closure, since that is where the link is created in JavaScript :-)
Yet, for utilizing this feature we do call the function from a different scope than what it was defined in - that's what the term "use a closure" in practise refers to. This can both be a lower or a higher scope - and the function does not necessarily need to be returned from the function where it was defined in.
Some examples:
var x = null;
function a() {
var i = "from a";
function b() {
alert(i); // reference to variable from a's scope
}
function c() {
var i = "c";
// use from lower scope
b(); // "from a" - not "c"
}
c();
// export by argument passing
[0].forEach(b); // "from a";
// export by assigning to variable in higher scope
x = b;
// export by returning
return b;
}
var y = a();
x(); // "from a"
y(); // "from a"
The actual closure is a container for variables, so that a function can use variables from the scope where it is created.
Returning a function is one way of using it in a different scope from where it is created, but a more common use is when it's a callback from an asynchronous call.
Any situation where a function uses variables from one scope, and the function is used in a different scope uses a closure. Example:
var globalF; // a global variable
function x() { // just to have a local scope
var local; // a local variable in the scope
var f = function(){
alert(local); // use the variable from the scope
};
globalF = f; // copy a reference to the function to the global variable
}
x(); // create the function
globalF(); // call the function
(This is only a demonstration of a closure, having a function set a global variable which is then used is not a good way to write actual code.)
a collection of explanations of closure below. to me, the one from "tiger book" satisfies me most...metaphoric ones also help a lot, but only after encounterred this one...
closure: in set theory, a closure is a (smallest) set, on which some operations yields results also belongs to the set, so it's sort of "smallest closed society under certain operations".
a) sicp: in abstract algebra, where a set of elements is said to be closed under an operation if applying the operation to elements in the set produces an element that is again an element of the set. The Lisp community also (unfortunately) uses the word "closure" to describe a totally unrelated concept: a closure is an implementation technique for representing procedures with free variables.
b) wiki: a closure is a first class function which captures the lexical bindings of free variables in its defining environment. Once it has captured the lexical bindings the function becomes a closure because it "closes over" those variables.”
c) tiger book: a data structure on heap (instead of on stack) that contains both function pointer (MC) and environment pointer (EP), representing a function variable;
d) on lisp: a combination of a function and a set of variable bindings is called a closure; closures are functions with local state;
e) google i/o video: similar to a instance of a class, in which the data (instance obj) encapsulates code (vtab), where in case of closure, the code (function variable) encapsulates data.
f) the encapsulated data is private to the function variable, implying closure can be used for data hiding.
g) closure in non-functional programming languages: callback with cookie in C is a similar construct, also the glib "closure": a glib closure is a data structure encapsulating similar things: a signal callback pointer, a cookie the private data, and a destructor of the closure (as there is no GC in C).
h) tiger book: "higher-order function" and "nested function scope" together require a solution to the case that a dad function returns a kid function which refers to variables in the scope of its dad implying that even dad returns the variables in its scope cannot be "popup" from the stack...the solution is to allocate closures in heap.
i) Greg Michaelson ($10.15): (in lisp implementation), closure is a way to identify the relationship betw free variables and lexical bound variables, when it's necessary (as often needed) to return a function value with free variables frozen to values from the defining scope.
j) histroy and etymology: Peter J. Landin defined the term closure in 1964 as having an environment part and a control part as used by his SECD machine for evaluating expressions. Joel Moses credits Landin with introducing the term closure to refer to a lambda expression whose open bindings (free variables) have been closed by (or bound in) the lexical environment, resulting in a closed expression, or closure. This usage was subsequently adopted by Sussman and Steele when they defined Scheme in 1975, and became widespread.

Determine the set of variables accessible within a JavaScript closure

"[JavaScript functions] internally store any variables they may refer to that are defined in their enclosing scopes."
How can I determine what that set of variables is?
For example, David Herman in Effective JavaScript gives this function (and closure):
function sandwichMaker() {
var magicIngredient = "peanut butter";
function make(filling) {
return magicIngredient + " and " + filling;
}
return make;
}
var f = sandwichMaker();
document.writeln("<p>" + f("jelly") + "</p>");
document.writeln("<p>" + f("bananas") + "</p>");
document.writeln("<p>" + f("marshmallows") + "</p>");
Sure, magicIngredient is a variable accessible to make(), but what else is? What if sandwichMaker were itself within a function? And then there are the globals. What is the function looking at when it looks for relevant values within the current scope?
What if sandwichMaker were itself within a function? And then there are the globals.
Yes, all the variables from parent functions are accessible (if they are not shadowed). And the highest-scoped function inherits from the global scope then.
What is the function looking at when it looks for relevant values within the current scope?
You can inspect that with a debugger. Insert a debugger; statement in make, and then execute it and have a look into your devtools. You will see something like this:
Scope Chain
0. make (currently executed):
this: (+)Window
arguments: (+)Arguments
filling "jelly"
1. sandwichMaker:
arguments: (+)Arguments
magicIngredient: "peanut butter"
make: (+)Function
Global
AnonXMLHttpRequest: …
ApplicationCache: …
Array: …
…
Also have a look at this great article: http://dmitrysoshnikov.com/ecmascript/es5-chapter-3-2-lexical-environments-ecmascript-implementation/
Example view at Chrome Devtools:
(from www.briangrinstead.com):
JavaScript uses function scope. This is pretty simple to understand - anything declared in a function has scope to that function as well as any higher scopes.
A closure can be thought of as two things being combined together: a particular scope, and a particular point in time (when the function was created).
Sure, magicIngredient is a variable accessible to make(), but what
else is?
Anything that was accessible to the scope of make at the time it was created. This includes all variables in the make function as well as any higher scopes. The scope of make is said to be closed-over the scope that existed at the point in time it was created, always giving it access to magicIngredient.
What if sandwichMaker were itself within a function?
Then make would have access to that scope (as it existed at the time make was created) as well.
And then there are the globals. What is the function looking at when it looks
for relevant values within the current scope?
The interpreter will search the currently executing scope for any referenced variables. If it can't find them, it will look in the next higher scope. It will continue looking higher and higher until it finds the variable or runs out of scopes (the global scope is the highest, aka the window object for javascript running in a browser).
A related concept is shadowing - two variables can have the same name in parent/child scopes, the child is said to "shadow" the parent because it will take precedence. Note this is a bad practice.
The easiest way to understand how closures and scoping works is to understand a simple factory pattern, such as this one. When the inner function is created and returned, it is bound to that scope at that point in time and will continue to alert the proper values even after the values no longer exist.
Hope this helped - lots of questions stuffed into one question :)
Suppose above function sandwichMaker() there was a variable defined...
var something = 'something';
function sandwichMaker () {
...
You can access something from within sandwichMaker() AND from within make().
The outer variables are accessible from within the functions. If you were to set var something = 'something else' within make(), then you would be effectively hiding the outer var something while within the make() function itself. However, you can just set something = 'something else', and the value will have changed at all scopes. It only hides the value if you declare that variable again.

But var it is not for local variable?

This is my code :
var markers={};
example();
function example() {
var myFunct = function () {
alert("hello");
};
markers["myIndex"] = myFunct;
}
markers["myIndex"]();
as you can see, myFunct is "var" (so, when example() finish, it will be destroyed, because it is local). But in fact, accessing to markers["myIndex"](), the function is referenced, and I can access to it. Why?
This doesn't work the way you expect it to. In other words, when example() finishes, myFunct will not be destroyed because there is still a reference to that function in a variable from an outer scope, markers.
The only way it would be 'destroyed' is if nothing else referenced it at the end of example() or if only variables with equal or lower scope referenced it, provided those variables also followed the same rules and were not referenced from outer variables.
In JavaScript, functions are objects just like other objects. When you do this:
var myFunct = function () {
alert("hello");
};
...you're creating a function and assigning a reference to that function to the variable myFunct. Then when you do this:
markers["myIndex"] = myFunct;
...you're assigning another reference to that function to markers["myIndex"]. So regardless of anything else that might happen to the myFunct variable, because markers["myIndex"] still has a reference to the function, the function is kept in memory.
But separately, there's a more subtle misunderstanding in your question as well: You've said:
myFunct is "var" (so, when example() finish, it will be destroyed, because it is local)
That's not true in JavaScript. In JavaScript, local variables are actually properties of a hidden object, called (deep breath) the variable binding object of the execution context (let's just call it the "variable object"). This object is associated with the particular call to example: It's created when the call to example is executed. Now, in the normal course of things, when example returns, if nothing has any outstanding reference to the variable object, then you're quite correct that it is eligible for garbage collection. But in your case, something does have a reference to the variable object: The function you created. When you create a function, it receives an implicit reference to the variable object for the context in which it was created, and it keeps that reference for as long as the function exists. So even though the function you're creating doesn't refer to anything in the variable object for the call to example, it has that reference to it nevertheless, and the variable object cannot be reclaimed until or unless nothing has a reference to the function anymore. This is how closures work. The foregoing text notwithstanding, closures are not complicated, they're really, really simple when you understand how they work.
(I'll just note here that some JavaScript engines introspect the code sufficiently that they can reclaim variable objects even when there are outstanding closures that refer to them. Specifically, if the closures [functions] don't actually use any of the variable object's properties, and they don't use eval, then the engine may be able to release the variable object. Chrome's V8 engine does this, for instance. But that's a runtime optimization; the concept is as described above.)
Because you have assigned it to the global variable markers from within your example function.
you're assigning a reference to the function object to a higher scope (if not global scope) object. So while myFunct would be garbage collected, the function is not, since there is another reference to it in the markers object.
A reference from var myFunct to the actual function object (function() { ... }) will indeed be destroyed. But the object itself will not, as it is referenced by a markers field. Once there are no live references to the function object from live JS objects, this function object will be eligible for garbage collection.

OO Javascript : Definitive explanation of variable scope

Can someone provide an explanation of variable scope in JS as it applies to objects, functions and closures?
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.
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/
Functions introduce a scope. You can declare functions inside other functions, thereby creating a nested scope. The inner scope can access the outer scope, but the outer can not access the inner scope.
Variables are bound to a scope, using the var keyword. All variables are implicitly bound to the top-level scope. So if you omit the var keyword, you are implicitly referring to a variable bound to the top level. In a browser, the top level is the window object. Note that window is it self a variable, so window == window.window

Categories

Resources