JavaScript Scope and Execution Context - javascript

I am trying to understand JavaScript scope rules. What I have read in textbooks and the documentation is confusing.
It seems to me that JavaScript is a statically (or lexically) scoped language - when trying to bind a variable name to a variable (definition), the lexical structure of the code is used.
An execution context seems to be similar to a stack frame on the call stack. Each execution context has a variable object upon which all the local variables (of the associated function) are defined. These variable objects are linked together to provide a 'scope chain' from the variable object at the top of the stack to the variable object at the bottom of the stack (the window object). This scope chain is searched from top to bottom in binding variable names to variables. This is very similar to statically scoped languages like C/C++/Java.
There seems to be one important difference with respect to C/C++/Java -- it is possible to access a variable defined in a function whose stack frame is no longer on the call stack, as shown in the example below:
var color = "red";
var printColor;
function changeColor() {
var color = "green";
printColor = function(msg) {
alert(msg + color);
}
printColor("in changeColor context, color = "); // "green"
}
changeColor();
// stack frame for "changeColor" no longer on stack
// but we can access the value of the variable color defined in that function
printColor("in global context, color = "); // "green"
Have I got this right? Are there other issues I should be aware of?
Thanks in advance

This is indeed a major difference between C/C++ and JavaScript: JavaScript is
a reference-counted, garbage-collected language, which means that objects can
be reclaimed by the engine when they no longer have any references to them.
The function you assign to printColor isn't on the stack, per se, as it
would be in C or C++; it's allocated dynamically and then assigned to
a variable outside your current scope. So, when control flow returns from
changeColor, the anonymous function still has a reference count of 1
since the outer printColor refers to it, and thus it's usable from the outer
scope.
So, your example isn't so much of a scoping issue--it's clear that you declare
printColor outside of the function scope of changeColor. When you define
changeColor, it
closes the upvalue
printColor into the new function scope, making it accessible. Like
Combat said, if you add a var to the second, inner definition of
printColor, it'll
shadow the first
printColor you declared and it won't be accessible outside that function
block.
As far as other issues to be aware of, yes, there are quite a few, but see my
comment on your original post for a good start.

It always comes down to lexical scoping which is function are executed with its scope chain when it is defined, not when it is invoked.
The anonymous function is defined in the local scope of function changeColor instead of the global scope. Hence when it is executed again, it prints out the color green which is listed in the local scope of function changeColor.

Related

JavaScript Closures - function scope [duplicate]

This question already has answers here:
How are closures and scopes represented at run time in JavaScript
(2 answers)
About closure, LexicalEnvironment and GC
(3 answers)
Closed 5 years ago.
I have a question related to JavaScript Closures, in specific to the scope when calling a (inner) function.
The question also relates to browser memory leaking as we will see.
At first a "short" introduction to my problem:
So I know when a function is called it enters an execution context (which is added on top of the call stack). There an "Activation object" is created with all the local variables, the function's arguments object and parameters added to it (as properties).
Since inner functions can access variables of enclosing functions - even if the inner function is called after the execution of its enclosing function has ended - there has to be some reference to the "free" (= outer) variables. This is managed by the scope chain which is also added to the execution context.
According to this site, the execution context's scope consists of the actual Activation object at the top of a list which is hiddenly saved on the function itself:
A scope consists of a list (or chain) of objects. Each function object has an internal [[scope]] property [...] The scope that is assigned to the execution context of a function call consists of the list referred to by the [[scope]] property of the corresponding function object with the Activation object added at the front of the chain (or the top of the list).
This is completely logic because due to this internal scope property, references to the free variables exist and so firstly the Closure is able to reach the variables (by going through the scope chain) and secondly it prevents the Garbage Collector from freeing the associated memory when the execution of the enclosing function ends.
In short: the scope chain (including the function's internal scope property) is the reason why Closures work as they do.
So now concretely to my question:
Which variables are added to the function's internal scope property?
As i understand the following part of this MDN article:
A closure is the combination of a function and the lexical environment within which that function was declared. This environment consists of any local variables that were in-scope at the time that the closure was created.
... this would mean that references to all local variables would be added to the internal scope property when forming a Closure.
This seems a bit unnecessary, when the Closure doesn't use all the local variables from its enclosing function, but no matter; the real problem is that this would lead to memory leaks as we will see in the following.
Consider following code (it's a small reduction of this article, to which we will come to later):
var theThing = null;
var replaceThing = function () {
var priorThing = theThing; // hold on to the prior thing
theThing = {
longStr: new Array(1000000).join('*'), // create a 1MB object
someMethod: function () {
console.log("someMessage");
}
};
};
setInterval(replaceThing, 1000); // invoke `replaceThing' once every second
After the first function call of replaceThing following would happen:
priorThing = null
theThing references to a new object (let's say with address 0x01) containing following properties:
a 1MB object
function someMethod whose internal scope property has references to all local variables of the enclosing function, this means also to priorThing which is null
After the second function call:
priorThing = reference to object with address 0x01
theThing references to a new object (let's say with address 0x02) containing following properties:
a 1MB object
function someMethod whose internal scope property has a reference to priorThing (with the address 0x01)
priorThing itself points to a object with the same structure ...
So what's happening?
On each function call a new object is created which references to the object created in the function call before; although we don't even use this object in our new object. It just happens due to the scope chain of the function closure.
So we see saving references to all local variables of the enclosing function is pretty bad.
A better way would be to just save these we really need.
So, from the previous article I conclude that this is really done so and this would solve the memory leak problem I described above.
But furthermore it says following:
But as soon as a variable is used by any closure, it ends up in the lexical environment shared by all closures in that scope.
Well, this would create another possibility to create memory leaks as the author describes in his example - but this would be a programmer's bug.
Okey, so now summed up shortly:
Are all local variables referenced in the closure's scope? (as MDN says)
Would be the worst, because of memory leaks.
Are the variables referenced by all closures if any closure uses it? (as this source says)
Would be the best, because memory leaks are avoided - but bugs could happen, if the programmer isn't aware of this behaviour.
Or does every closure have its own references depending on which variables are used by themselves?
Would completely avoid memory leaks, but a bit more memory would be needed because there has to be a own "lexical environment" object (which is referenced by the internal scope property) for each closure.

Javascript - understanding the scope chain's reference priority

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).

javascript function object's [[scope]] property?

ok this is some code
function myFunc(){
var myvar = 8;
function myFunc2(num){
alert(myvar+num);
}
myFunc2(2);
}
myFunc();
i want to clear my mind so pls correct me if am wrong
i have read allot of articles in stack overflow already but i want to know i understand it well or should i read more.
to my understanding what happens behind the scene is thatin global execution context there it creates function object with the namemyFunc` and its [[scope]] property assigned to global variable object.
and when i call myFunc it creates its own execution context and activation object where all of the function's arguments and function declaration is initialized before any line by line code execution.
when inner function object is created it's internal [[scope]] property is assigned the value of its outer execution context's variable object + global variable object so every function creates its own execution context but before that every function's internal [[scope]] property is assigned first.
i have read allot of articles in stack overflow already but i want to know i understand it well or should i read more.
Here are a couple of pointers based on my understanding of the specification, and based on what sounds unclear on your explanation:
The term "Activation object" was used in ECMAScript 3, but not anymore in the current version of the specification. ES5 uses the term "Lexical Environment" to denote a type (an internal type) consisting of an "Environment Record" value, and possibly a reference to an outer Lexical Environment.
Because of this reference to an outer Lexical Environment, scope can be thought of as a chain. So access to outer scopes (including the global scope) happens through that chain. (When you say that "[[scope]] property is assigned the value of its outer execution context's variable object + global variable object", it sounds like both records are copied into the current function's Lexical Environment, which is not how it happens.)
Hope this helps!

What is the 'Execution Context' in JavaScript exactly?

My title pretty much sums it all.
Can anyone enlighten me on...
"What is the 'Execution Context' in JavaScript?"
and on how it relates to 'this,' hoisting, prototype chaining, scope and garbage collection?
You're asking about several different concepts that aren't very closely related. I'll try to briefly address each.
Execution context is a concept in the language spec that—in layman's terms—roughly equates to the 'environment' a function executes in; that is, variable scope (and the scope chain, variables in closures from outer scopes), function arguments, and the value of the this object.
The call stack is a collection of execution contexts.
See also this answer and this article.
Scope is literally that: the scope in which a variable can be accessed. Simplistically:
var x;
function a() {
var y;
}
x can be accessed from anywhere. When a is invoked, x will be in the outer scope. (Stored in the scope chain.)
In contrast, y can only be accessed by code in a() because it is limited to a's scope. This is what the var keyword does: restricts a variable to the local scope. If we omitted var, y would end up in the global scope, generally considered a bad thing.
Think of hoisting as more of a compile-time thing. In JavaScript, function declarations are "hoisted" to the top of their scope. In other words, they are parsed and evaluated before any other code. (This is opposed to function expressions, which are evaluated inline.) Consider the following:
a();
b();
function a() { }
var b = function() { }
The call to a() will succeed because its declaration was hoisted to the top; a was assigned to automatically before program execution began. The call to b() will fail with a TypeError because b will not be defined until line 4.
You have asked so many concepts but lets pick one by one & understand them.
The environment in which your code is running is Execution context.
It is created when your code is executed.
Execution Context (Global), created by JS Engine contains 3 important things for you:
Global object - window
Special Object this
Ref to outer environment
Lets see a simple example to understand Global Execution Context:
var a = "Hello World";
function b(){
}
When JS Engine runs this above code it creates following Execution context (shown in image):
Global Execution Context
Now let's see how JS Engine creates Execution Context (then we will dig out & understand hoisting):
consider this scenario:
b();
console.log(a);
var a = "Hello World!";
function b(){
console.log("Called b!");
}
I can call the function b() even though it is declared later.
This means JS Engine is doing something before my code is executed, lets see what:
JS Engine performs following two steps to while executing any code:
CREATION PHASE :
JS Engine parses - run through your code & identifies variables & functions created by code (which will be used in execution phase)
Setup memory space for Variables & Functions - "Hoisting"
Hoisting - before your code is executed, the JS Engine set asides memory space for Var & Func used inside the code.
These variables & functions comprise the Execution Context of any function that is be executed.
All variables in JS are initially set to undefined.
Execution PHASE: pretty simple to understand,
When the code is executed line-by-line (by JS interpreeter) it can
access the variables defined inside Execution Context
variable assignment are done in this phase
A new Execution Context is created whenever function invocation is there
Execution Context Stack:
What happens when you invoke a function:
function b(){
}
function a(){
b();
}
a();
Now first of all Global Execution Context is going to be created
(as explained above)
then execution starts and interpreeter encounters call to function
a(), and here a new execution context is created pushed on top EC
Stack
so anytime you invoke a function a new EC is created & placed on top of EC Stack.
so now EC for a() is CREATED interpreeter will execute the code
inside a() line-by-line
then intrepreeter encounters call to function b(), this creates
another EC which is pushed on top or EC stack
When b() finishes it will be popped-off the stack then a() will finish &
all the way down to Global EC
see Execution Stack for above code snippet
I have addressed only the topics that are most closely related.
Execution Context is the wrapper around your existing code; which contains code that you have not written; but is generated by the JS Engine.
It comprises of the following -
Global Object
'this'
Outer environment
Your code
An Execution Context is created each time you run your .js file/app. The first step in this creation phase is Hoisting. The JS Engine reserves space or set's up memory for all the variables and functions defined in your code. These are then accessed when your code is executed line-by-line.
For example:
b();
console.log(a);
var a = "hi!";
function b() {
console.log("calling function");
}
Here, the function b() and variable a are both accessed before they are defined, however, due to hoisting the console will not throw any error.
The output will look like - (try it)
calling function
undefined
Notice how the function was executed completely, but we have undefined for the variable. This is because Hoisting is performed differently for functions vs variables. The function as a whole is picked up into the memory, but for the variables, space is reserved as a placeholder with the value of undefined. The actual value is then replaced when the engine executes your code line-by-line.
I hope this clears the concept for you.
I would like to address
Context
this context (relation with context)
Scope
1 : Execution Context
JavaScript is a single threaded language, meaning only one task can be executed at a time. When the JavaScript interpreter initially executes code, it first enters into a global execution context by default. Each invocation of a function from this point on will result in the creation of a new execution context.
This is where confusion often sets in, the term execution context is actually for all intents and purposes referring more to scope and not context. It is an unfortunate naming convention, however it is the terminology as defined by the ECMAScript specification, so we’re kinda stuck with it.
Each time a new execution context is created it is appended to the top of the execution stack. The browser will always execute the current execution context that is atop the execution stack. Once completed, it will be removed from the top of the stack and control will return to the execution context below.
An execution context can be divided into a creation and execution phase. In the creation phase, the interpreter will first create a variable object (also called an activation object) that is composed of all the variables, function declarations, and arguments defined inside the execution context. From there the scope chain is initialized next, and the value of this is determined last. Then in the execution phase, code is interpreted and executed.
2 : this Context
What is “this” Context?
Context is most often determined by how a function is invoked. When a function is called as a method of an object, this is set to the object the method is called on:
var obj = {
foo: function() {
return this;
}
};
obj.foo() === obj; // true
The same principle applies when invoking a function with the new operator to create an instance of an object. When invoked in this manner, the value of this within the scope of the function will be set to the newly created instance:
function foo() {
alert(this);
}
foo() // window
new foo() // foo
When called as an unbound function, this will default to the global context or window object in the browser. However, if the function is executed in strict mode, the context will default to undefined.
3 : Variable scope
A variable can be defined in either local or global scope, which establishes the variables’ accessibility from different scopes during runtime. Any defined global variable, meaning any variable declared outside of a function body will live throughout runtime and can be accessed and altered in any scope. Local variables exist only within the function body of which they are defined and will have a different scope for every call of that function. There it is subject for value assignment, retrieval, and manipulation only within that call and is not accessible outside of that scope.
ECMAScript 6 (ES6/ES2015) introduced the let and const keywords that support the declaration of block scope local variables. This means the variable will be confined to the scope of a block that it is defined in, such as an if statement or for loop and will not be accessible outside of the opening and closing curly braces of the block. This is contrary to var declarations which are accessible outside blocks they are defined in. The difference between let and const is that a const declaration is, as the name implies, constant - a read-only reference to a value. This does not mean the value is immutable, just that the variable identifier cannot be reassigned.
For Other topics:
GC : GC
Prototyping : Prototyping
The "Execution Context" is an umbrella that wraps all of the code to help manage it. It's like a manager that manages any environment. Since there's so many lexical environments because in a JavaScript application you have lots of variables and functions you need a way to manage everything. What comes first, what comes second and so on, and if you did not have an "Execution Context" environment everything goes to hell. So consider the "Execution Context" a wrapper, a manager that manages your code.
When you execute a function you create a new execution context comprising a local memory which is called a variable environment and this which is a placeholder, it will refer inside its execution context to whatever is the left of the . where that function is being called upon.
what is EC(Execution context) in JS ?
Simply put, an execution context is an abstract concept of an
environment where the Javascript code is evaluated and executed.
Whenever any code is run in JavaScript, it’s run inside an execution
context.
For more depth details : https://blog.bitsrc.io/understanding-execution-context-and-execution-stack-in-javascript-1c9ea8642dd0
I suppose a simple example would explain everything.
Note: function.call(object) calls function function in context of object
// HTML
​<p id="p"></p>​​​​​​​​​​​​​​​​​​​​​​​​
// JavaScript
function helloWorld() {
alert("HelloWorld: " + this);
}
var p = document.getElementById("p");
helloWorld(); // HelloWorld: [object DOMWindow]
helloWorld.call(window); // HelloWorld: [object DOMWindow]
​​​​​​helloWorld.call("String"); // HelloWorld: String // Note: "toString()"
helloWorld.call​​​​(p); // HelloWorld: [object HTMLParagraphElement]
helloWorld.call(new Date());​​​​ // HelloWorld: Tue Feb 21 2012 21:45:17 GMT+0100 (Central Europe Standard Time)
Execution Context is a wrapper to help manage the code that is running.
In your code you will see lots of lexical environments (which means areas of the code between { ... }) but which one is currently running is managed via execution contexts. It can contain your code and it also can contain beyond what you've written in your code.

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