What is the 'Execution Context' in JavaScript exactly? - javascript

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.

Related

In JS Engine, does the IIFE's execution context get created & exited BEFORE or AFTER the variable declaration?

Since all IIFEs are function expressions, like a function declaration, does JavaScript allocate memory BEFOREHAND(before running any code) for a function expression that is lexically inside the global execution context?
If yes, since functions get stored in memory first before variable declaration, the IIFE's execution context will exit even before the variables are declared because it is called immediately.
(function(){
console.log(foo); // (1)
})();
var foo=0;
(1): should return Uncaught ReferenceError: 'a' is not defined Error, but instead of a's value being undefined. Why?

Reassigning let variables [duplicate]

What is a brief introduction to lexical scoping?
I understand them through examples. :)
First, lexical scope (also called static scope), in C-like syntax:
void fun()
{
int x = 5;
void fun2()
{
printf("%d", x);
}
}
Every inner level can access its outer levels.
There is another way, called dynamic scope used by the first implementation of Lisp, again in a C-like syntax:
void fun()
{
printf("%d", x);
}
void dummy1()
{
int x = 5;
fun();
}
void dummy2()
{
int x = 10;
fun();
}
Here fun can either access x in dummy1 or dummy2, or any x in any function that call fun with x declared in it.
dummy1();
will print 5,
dummy2();
will print 10.
The first one is called static because it can be deduced at compile-time, and the second is called dynamic because the outer scope is dynamic and depends on the chain call of the functions.
I find static scoping easier for the eye. Most languages went this way eventually, even Lisp (can do both, right?). Dynamic scoping is like passing references of all variables to the called function.
As an example of why the compiler can not deduce the outer dynamic scope of a function, consider our last example. If we write something like this:
if(/* some condition */)
dummy1();
else
dummy2();
The call chain depends on a run time condition. If it is true, then the call chain looks like:
dummy1 --> fun()
If the condition is false:
dummy2 --> fun()
The outer scope of fun in both cases is the caller plus the caller of the caller and so on.
Just to mention that the C language does not allow nested functions nor dynamic scoping.
Lets try the shortest possible definition:
Lexical Scoping defines how variable names are resolved in nested functions: inner functions contain the scope of parent functions even if the parent function has returned.
That is all there is to it!
var scope = "I am global";
function whatismyscope(){
var scope = "I am just a local";
function func() {return scope;}
return func;
}
whatismyscope()()
The above code will return "I am just a local". It will not return "I am a global". Because the function func() counts where is was originally defined which is under the scope of function whatismyscope.
It will not bother from whatever it is being called(the global scope/from within another function even), that's why global scope value I am global will not be printed.
This is called lexical scoping where "functions are executed using the scope chain that was in effect when they were defined" - according to JavaScript Definition Guide.
Lexical scope is a very very powerful concept.
Lexical (AKA static) scoping refers to determining a variable's scope based solely on its position within the textual corpus of code. A variable always refers to its top-level environment. It's good to understand it in relation to dynamic scope.
Scope defines the area, where functions, variables and such are available. The availability of a variable for example is defined within its the context, let's say the function, file, or object, they are defined in. We usually call these local variables.
The lexical part means that you can derive the scope from reading the source code.
Lexical scope is also known as static scope.
Dynamic scope defines global variables that can be called or referenced from anywhere after being defined. Sometimes they are called global variables, even though global variables in most programmin languages are of lexical scope. This means, it can be derived from reading the code that the variable is available in this context. Maybe one has to follow a uses or includes clause to find the instatiation or definition, but the code/compiler knows about the variable in this place.
In dynamic scoping, by contrast, you search in the local function first, then you search in the function that called the local function, then you search in the function that called that function, and so on, up the call stack. "Dynamic" refers to change, in that the call stack can be different every time a given function is called, and so the function might hit different variables depending on where it is called from. (see here)
To see an interesting example for dynamic scope see here.
For further details see here and here.
Some examples in Delphi/Object Pascal
Delphi has lexical scope.
unit Main;
uses aUnit; // makes available all variables in interface section of aUnit
interface
var aGlobal: string; // global in the scope of all units that use Main;
type
TmyClass = class
strict private aPrivateVar: Integer; // only known by objects of this class type
// lexical: within class definition,
// reserved word private
public aPublicVar: double; // known to everyboday that has access to a
// object of this class type
end;
implementation
var aLocalGlobal: string; // known to all functions following
// the definition in this unit
end.
The closest Delphi gets to dynamic scope is the RegisterClass()/GetClass() function pair. For its use see here.
Let's say that the time RegisterClass([TmyClass]) is called to register a certain class cannot be predicted by reading the code (it gets called in a button click method called by the user), code calling GetClass('TmyClass') will get a result or not. The call to RegisterClass() does not have to be in the lexical scope of the unit using GetClass();
Another possibility for dynamic scope are anonymous methods (closures) in Delphi 2009, as they know the variables of their calling function. It does not follow the calling path from there recursively and therefore is not fully dynamic.
A lexical scope in JavaScript means that a variable defined outside a function can be accessible inside another function defined after the variable declaration. But the opposite is not true; the variables defined inside a function will not be accessible outside that function.
This concept is heavily used in closures in JavaScript.
Let's say we have the below code.
var x = 2;
var add = function() {
var y = 1;
return x + y;
};
Now, when you call add() --> this will print 3.
So, the add() function is accessing the global variable x which is defined before method function add. This is called due to lexical scoping in JavaScript.
Lexical scope means that in a nested group of functions, the inner functions have access to the variables and other resources of their parent scope.
This means that the child's functions are lexically bound to the execution context of their parents.
Lexical scope is sometimes also referred to as static scope.
function grandfather() {
var name = 'Hammad';
// 'likes' is not accessible here
function parent() {
// 'name' is accessible here
// 'likes' is not accessible here
function child() {
// Innermost level of the scope chain
// 'name' is also accessible here
var likes = 'Coding';
}
}
}
The thing you will notice about lexical scope is that it works forward, meaning the name can be accessed by its children's execution contexts.
But it doesn't work backward to its parents, meaning that the variable likes cannot be accessed by its parents.
This also tells us that variables having the same name in different execution contexts gain precedence from top to bottom of the execution stack.
A variable, having a name similar to another variable, in the innermost function (topmost context of the execution stack) will have higher precedence.
Source.
I love the fully featured, language-agnostic answers from folks like #Arak. Since this question was tagged JavaScript though, I'd like to chip in some notes very specific to this language.
In JavaScript our choices for scoping are:
as-is (no scope adjustment)
lexical var _this = this; function callback(){ console.log(_this); }
bound callback.bind(this)
It's worth noting, I think, that JavaScript doesn't really have dynamic scoping. .bind adjusts the this keyword, and that's close, but not technically the same.
Here is an example demonstrating both approaches. You do this every time you make a decision about how to scope callbacks so this applies to promises, event handlers, and more.
Lexical
Here is what you might term Lexical Scoping of callbacks in JavaScript:
var downloadManager = {
initialize: function() {
var _this = this; // Set up `_this` for lexical access
$('.downloadLink').on('click', function () {
_this.startDownload();
});
},
startDownload: function(){
this.thinking = true;
// Request the file from the server and bind more callbacks for when it returns success or failure
}
//...
};
Bound
Another way to scope is to use Function.prototype.bind:
var downloadManager = {
initialize: function() {
$('.downloadLink').on('click', function () {
this.startDownload();
}.bind(this)); // Create a function object bound to `this`
}
//...
These methods are, as far as I know, behaviorally equivalent.
In simple language, lexical scope is a variable defined outside your scope or upper scope is automatically available inside your scope which means you don't need to pass it there.
Example:
let str="JavaScript";
const myFun = () => {
console.log(str);
}
myFun();
// Output: JavaScript
Lexical scope means that a function looks up variables in the context where it was defined, and not in the scope immediately around it.
Look at how lexical scope works in Lisp if you want more detail. The selected answer by Kyle Cronin in Dynamic and Lexical variables in Common Lisp is a lot clearer than the answers here.
Coincidentally I only learned about this in a Lisp class, and it happens to apply in JavaScript as well.
I ran this code in Chrome's console.
// JavaScript Equivalent Lisp
var x = 5; //(setf x 5)
console.debug(x); //(print x)
function print_x(){ //(defun print-x ()
console.debug(x); // (print x)
} //)
(function(){ //(let
var x = 10; // ((x 10))
console.debug(x); // (print x)
print_x(); // (print-x)
})(); //)
Output:
5
10
5
Lexical scoping: Variables declared outside of a function are global variables and are visible everywhere in a JavaScript program. Variables declared inside a function have function scope and are visible only to code that appears inside that function.
IBM defines it as:
The portion of a program or segment unit in which a declaration
applies. An identifier declared in a routine is known within that
routine and within all nested routines. If a nested routine declares
an item with the same name, the outer item is not available in the
nested routine.
Example 1:
function x() {
/*
Variable 'a' is only available to function 'x' and function 'y'.
In other words the area defined by 'x' is the lexical scope of
variable 'a'
*/
var a = "I am a";
function y() {
console.log( a )
}
y();
}
// outputs 'I am a'
x();
Example 2:
function x() {
var a = "I am a";
function y() {
/*
If a nested routine declares an item with the same name,
the outer item is not available in the nested routine.
*/
var a = 'I am inner a';
console.log( a )
}
y();
}
// outputs 'I am inner a'
x();
I hope this is helpful, here is my attempt at a slightly more abstract definition:
Lexical scope:
The access or range something (e.g. a function or variable) has to other elements in the program as determined by its position in the source code.
Fwiw, my logic here simply builds from the definitions of:
Lexical: relating to the words or vocabulary of a language (specifically the word as separate from it's grammar or construction) {in our case - a programming language}.
Scope (noun): the range of operation {in our case the range is: what can be accessed}.
Note, the original 1960 definition of Lexical Scope from the ALGOL 60 spec is far more pithy than my attempt above:
Lexical scope: the portion of source code in which a binding of a name with an entity applies. source
Lexical scope refers to the lexicon of identifiers (e.g., variables, functions, etc.) visible from the current position in the execution stack.
- global execution context
- foo
- bar
- function1 execution context
- foo2
- bar2
- function2 execution context
- foo3
- bar3
foo and bar are always within the lexicon of available identifiers because they are global.
When function1 is executed, it has access to a lexicon of foo2, bar2, foo, and bar.
When function2 is executed, it has access to a lexicon of foo3, bar3, foo2, bar2, foo, and bar.
The reason global and/or outer functions do not have access to an inner functions identifiers is because the execution of that function has not occurred yet and therefore, none of its identifiers have been allocated to memory. What’s more, once that inner context executes, it is removed from the execution stack, meaning that all of it’s identifiers have been garbage collected and are no longer available.
Finally, this is why a nested execution context can ALWAYS access it’s ancestors execution context and thus why it has access to a greater lexicon of identifiers.
See:
https://tylermcginnis.com/ultimate-guide-to-execution-contexts-hoisting-scopes-and-closures-in-javascript/
https://developer.mozilla.org/en-US/docs/Glossary/Identifier
Special thanks to #robr3rd for help simplifying the above definition.
There is an important part of the conversation surrounding lexical and dynamic scoping that is missing: a plain explanation of the lifetime of the scoped variable - or when the variable can be accessed.
Dynamic scoping only very loosely corresponds to "global" scoping in the way that we traditionally think about it (the reason I bring up the comparison between the two is that it has already been mentioned - and I don't particularly like the linked article's explanation); it is probably best we don't make the comparison between global and dynamic - though supposedly, according to the linked article, "...[it] is useful as a substitute for globally scoped variables."
So, in plain English, what's the important distinction between the two scoping mechanisms?
Lexical scoping has been defined very well throughout the answers above: lexically scoped variables are available - or, accessible - at the local level of the function in which it was defined.
However - as it is not the focus of the OP - dynamic scoping has not received a great deal of attention and the attention it has received means it probably needs a bit more (that's not a criticism of other answers, but rather a "oh, that answer made we wish there was a bit more"). So, here's a little bit more:
Dynamic scoping means that a variable is accessible to the larger program during the lifetime of the function call - or, while the function is executing. Really, Wikipedia actually does a nice job with the explanation of the difference between the two. So as not to obfuscate it, here is the text that describes dynamic scoping:
...[I]n dynamic scoping (or dynamic scope), if a variable name's scope is a
certain function, then its scope is the time-period during which the
function is executing: while the function is running, the variable
name exists, and is bound to its variable, but after the function
returns, the variable name does not exist.
Ancient question, but here is my take on it.
Lexical (static) scope refers to the scope of a variable in the source code.
In a language like JavaScript, where functions can be passed around and attached and re-attached to miscellaneous objects, you might have though that scope would depend on who’s calling the function at the time, but it doesn’t. Changing the scope that way would be dynamic scope, and JavaScript doesn’t do that, except possibly with the this object reference.
To illustrate the point:
var a='apple';
function doit() {
var a='aardvark';
return function() {
alert(a);
}
}
var test=doit();
test();
In the example, the variable a is defined globally, but shadowed in the doit() function. This function returns another function which, as you see, relies on the a variable outside of its own scope.
If you run this, you will find that the value used is aardvark, not apple which, though it is in the scope of the test() function, is not in the lexical scope of the original function. That is, the scope used is the scope as it appears in the source code, not the scope where the function is actually used.
This fact can have annoying consequences. For example, you might decide that it’s easier to organise your functions separately, and then use them when the time comes, such as in an event handler:
var a='apple',b='banana';
function init() {
var a='aardvark',b='bandicoot';
document.querySelector('button#a').onclick=function(event) {
alert(a);
}
document.querySelector('button#b').onclick=doB;
}
function doB(event) {
alert(b);
}
init();
<button id="a">A</button>
<button id="b">B</button>
This code sample does one of each. You can see that because of lexical scoping, button A uses the inner variable, while button B doesn’t. You may end up nesting functions more than you would have liked.
By the way, in both examples, you will also notice that the inner lexically scoped variables persist even though the containing function function has run its course. This is called closure, and refers to a nested function’s access to outer variables, even if the outer function has finished. JavaScript needs to be smart enough to determine whether those variables are no longer needed, and if not, can garbage collect them.
Here's a different angle on this question that we can get by taking a step back and looking at the role of scoping in the larger framework of interpretation (running a program). In other words, imagine that you were building an interpreter (or compiler) for a language and were responsible for computing the output, given a program and some input to it.
Interpretation involves keeping track of three things:
State - namely, variables and referenced memory locations on the heap and stack.
Operations on that state - namely, every line of code in your program
The environment in which a given operation runs - namely, the projection of state on an operation.
An interpreter starts at the first line of code in a program, computes its environment, runs the line in that environment and captures its effect on the program's state. It then follows the program's control flow to execute the next line of code, and repeats the process till the program ends.
The way you compute the environment for any operation is through a formal set of rules defined by the programming language. The term "binding" is frequently used to describe the mapping of the overall state of the program to a value in the environment. Note that by "overall state" we do not mean global state, but rather the sum total of every reachable definition, at any point in the execution).
This is the framework in which the scoping problem is defined. Now to the next part of what our options are.
As the implementor of the interpreter, you could simplify your task by making the environment as close as possible to the program's state. Accordingly, the environment of a line of code would simply be defined by environment of the previous line of code with the effects of that operation applied to it, regardless of whether the previous line was an assignment, a function call, return from a function, or a control structure such as a while loop.
This is the gist of dynamic scoping, wherein the environment that any code runs in is bound to the state of the program as defined by its execution context.
Or, you could think of a programmer using your language and simplify his or her task of keeping track of the values a variable can take. There are way too many paths and too much complexity involved in reasoning about the outcome the totality of past execution. Lexical Scoping helps do this by restricting the current environment to the portion of state defined in the current block, function or other unit of scope, and its parent (i.e. the block enclosing the current clock, or the function that called the present function).
In other words, with lexical scope the environment that any code sees is bound to state associated with a scope defined explicitly in the language, such as a block or a function.
Scope is the context within which a variable/binding is accessible. Lexical scope means local to the enclosing lexical block or blocks as opposed to for instance global scope.
This topic is strongly related with the built-in bind function and introduced in ECMAScript 6 Arrow Functions. It was really annoying, because for every new "class" (function actually) method we wanted to use, we had to bind this in order to have access to the scope.
JavaScript by default doesn't set its scope of this on functions (it doesn't set the context on this). By default you have to explicitly say which context you want to have.
The arrow functions automatically gets so-called lexical scope (have access to variable's definition in its containing block). When using arrow functions it automatically binds this to the place where the arrow function was defined in the first place, and the context of this arrow functions is its containing block.
See how it works in practice on the simplest examples below.
Before Arrow Functions (no lexical scope by default):
const programming = {
language: "JavaScript",
getLanguage: function() {
return this.language;
}
}
const globalScope = programming.getLanguage;
console.log(globalScope()); // Output: undefined
const localScope = programming.getLanguage.bind(programming);
console.log(localScope()); // Output: "JavaScript"
With arrow functions (lexical scope by default):
const programming = {
language: "JavaScript",
getLanguage: function() {
return this.language;
}
}
const arrowFunction = () => {
console.log(programming.getLanguage());
}
arrowFunction(); // Output: "JavaScript"
Lexical scoping means functions resolve free variables from the scope where they were defined, not from the scope where they are called.
I normally learn by example, and here's a little something:
const lives = 0;
function catCircus () {
this.lives = 1;
const lives = 2;
const cat1 = {
lives: 5,
jumps: () => {
console.log(this.lives);
}
};
cat1.jumps(); // 1
console.log(cat1); // { lives: 5, jumps: [Function: jumps] }
const cat2 = {
lives: 5,
jumps: () => {
console.log(lives);
}
};
cat2.jumps(); // 2
console.log(cat2); // { lives: 5, jumps: [Function: jumps] }
const cat3 = {
lives: 5,
jumps: () => {
const lives = 3;
console.log(lives);
}
};
cat3.jumps(); // 3
console.log(cat3); // { lives: 5, jumps: [Function: jumps] }
const cat4 = {
lives: 5,
jumps: function () {
console.log(lives);
}
};
cat4.jumps(); // 2
console.log(cat4); // { lives: 5, jumps: [Function: jumps] }
const cat5 = {
lives: 5,
jumps: function () {
var lives = 4;
console.log(lives);
}
};
cat5.jumps(); // 4
console.log(cat5); // { lives: 5, jumps: [Function: jumps] }
const cat6 = {
lives: 5,
jumps: function () {
console.log(this.lives);
}
};
cat6.jumps(); // 5
console.log(cat6); // { lives: 5, jumps: [Function: jumps] }
const cat7 = {
lives: 5,
jumps: function thrownOutOfWindow () {
console.log(this.lives);
}
};
cat7.jumps(); // 5
console.log(cat7); // { lives: 5, jumps: [Function: thrownOutOfWindow] }
}
catCircus();

Lexical Scope & Closures [duplicate]

What is a brief introduction to lexical scoping?
I understand them through examples. :)
First, lexical scope (also called static scope), in C-like syntax:
void fun()
{
int x = 5;
void fun2()
{
printf("%d", x);
}
}
Every inner level can access its outer levels.
There is another way, called dynamic scope used by the first implementation of Lisp, again in a C-like syntax:
void fun()
{
printf("%d", x);
}
void dummy1()
{
int x = 5;
fun();
}
void dummy2()
{
int x = 10;
fun();
}
Here fun can either access x in dummy1 or dummy2, or any x in any function that call fun with x declared in it.
dummy1();
will print 5,
dummy2();
will print 10.
The first one is called static because it can be deduced at compile-time, and the second is called dynamic because the outer scope is dynamic and depends on the chain call of the functions.
I find static scoping easier for the eye. Most languages went this way eventually, even Lisp (can do both, right?). Dynamic scoping is like passing references of all variables to the called function.
As an example of why the compiler can not deduce the outer dynamic scope of a function, consider our last example. If we write something like this:
if(/* some condition */)
dummy1();
else
dummy2();
The call chain depends on a run time condition. If it is true, then the call chain looks like:
dummy1 --> fun()
If the condition is false:
dummy2 --> fun()
The outer scope of fun in both cases is the caller plus the caller of the caller and so on.
Just to mention that the C language does not allow nested functions nor dynamic scoping.
Lets try the shortest possible definition:
Lexical Scoping defines how variable names are resolved in nested functions: inner functions contain the scope of parent functions even if the parent function has returned.
That is all there is to it!
var scope = "I am global";
function whatismyscope(){
var scope = "I am just a local";
function func() {return scope;}
return func;
}
whatismyscope()()
The above code will return "I am just a local". It will not return "I am a global". Because the function func() counts where is was originally defined which is under the scope of function whatismyscope.
It will not bother from whatever it is being called(the global scope/from within another function even), that's why global scope value I am global will not be printed.
This is called lexical scoping where "functions are executed using the scope chain that was in effect when they were defined" - according to JavaScript Definition Guide.
Lexical scope is a very very powerful concept.
Lexical (AKA static) scoping refers to determining a variable's scope based solely on its position within the textual corpus of code. A variable always refers to its top-level environment. It's good to understand it in relation to dynamic scope.
Scope defines the area, where functions, variables and such are available. The availability of a variable for example is defined within its the context, let's say the function, file, or object, they are defined in. We usually call these local variables.
The lexical part means that you can derive the scope from reading the source code.
Lexical scope is also known as static scope.
Dynamic scope defines global variables that can be called or referenced from anywhere after being defined. Sometimes they are called global variables, even though global variables in most programmin languages are of lexical scope. This means, it can be derived from reading the code that the variable is available in this context. Maybe one has to follow a uses or includes clause to find the instatiation or definition, but the code/compiler knows about the variable in this place.
In dynamic scoping, by contrast, you search in the local function first, then you search in the function that called the local function, then you search in the function that called that function, and so on, up the call stack. "Dynamic" refers to change, in that the call stack can be different every time a given function is called, and so the function might hit different variables depending on where it is called from. (see here)
To see an interesting example for dynamic scope see here.
For further details see here and here.
Some examples in Delphi/Object Pascal
Delphi has lexical scope.
unit Main;
uses aUnit; // makes available all variables in interface section of aUnit
interface
var aGlobal: string; // global in the scope of all units that use Main;
type
TmyClass = class
strict private aPrivateVar: Integer; // only known by objects of this class type
// lexical: within class definition,
// reserved word private
public aPublicVar: double; // known to everyboday that has access to a
// object of this class type
end;
implementation
var aLocalGlobal: string; // known to all functions following
// the definition in this unit
end.
The closest Delphi gets to dynamic scope is the RegisterClass()/GetClass() function pair. For its use see here.
Let's say that the time RegisterClass([TmyClass]) is called to register a certain class cannot be predicted by reading the code (it gets called in a button click method called by the user), code calling GetClass('TmyClass') will get a result or not. The call to RegisterClass() does not have to be in the lexical scope of the unit using GetClass();
Another possibility for dynamic scope are anonymous methods (closures) in Delphi 2009, as they know the variables of their calling function. It does not follow the calling path from there recursively and therefore is not fully dynamic.
A lexical scope in JavaScript means that a variable defined outside a function can be accessible inside another function defined after the variable declaration. But the opposite is not true; the variables defined inside a function will not be accessible outside that function.
This concept is heavily used in closures in JavaScript.
Let's say we have the below code.
var x = 2;
var add = function() {
var y = 1;
return x + y;
};
Now, when you call add() --> this will print 3.
So, the add() function is accessing the global variable x which is defined before method function add. This is called due to lexical scoping in JavaScript.
Lexical scope means that in a nested group of functions, the inner functions have access to the variables and other resources of their parent scope.
This means that the child's functions are lexically bound to the execution context of their parents.
Lexical scope is sometimes also referred to as static scope.
function grandfather() {
var name = 'Hammad';
// 'likes' is not accessible here
function parent() {
// 'name' is accessible here
// 'likes' is not accessible here
function child() {
// Innermost level of the scope chain
// 'name' is also accessible here
var likes = 'Coding';
}
}
}
The thing you will notice about lexical scope is that it works forward, meaning the name can be accessed by its children's execution contexts.
But it doesn't work backward to its parents, meaning that the variable likes cannot be accessed by its parents.
This also tells us that variables having the same name in different execution contexts gain precedence from top to bottom of the execution stack.
A variable, having a name similar to another variable, in the innermost function (topmost context of the execution stack) will have higher precedence.
Source.
I love the fully featured, language-agnostic answers from folks like #Arak. Since this question was tagged JavaScript though, I'd like to chip in some notes very specific to this language.
In JavaScript our choices for scoping are:
as-is (no scope adjustment)
lexical var _this = this; function callback(){ console.log(_this); }
bound callback.bind(this)
It's worth noting, I think, that JavaScript doesn't really have dynamic scoping. .bind adjusts the this keyword, and that's close, but not technically the same.
Here is an example demonstrating both approaches. You do this every time you make a decision about how to scope callbacks so this applies to promises, event handlers, and more.
Lexical
Here is what you might term Lexical Scoping of callbacks in JavaScript:
var downloadManager = {
initialize: function() {
var _this = this; // Set up `_this` for lexical access
$('.downloadLink').on('click', function () {
_this.startDownload();
});
},
startDownload: function(){
this.thinking = true;
// Request the file from the server and bind more callbacks for when it returns success or failure
}
//...
};
Bound
Another way to scope is to use Function.prototype.bind:
var downloadManager = {
initialize: function() {
$('.downloadLink').on('click', function () {
this.startDownload();
}.bind(this)); // Create a function object bound to `this`
}
//...
These methods are, as far as I know, behaviorally equivalent.
In simple language, lexical scope is a variable defined outside your scope or upper scope is automatically available inside your scope which means you don't need to pass it there.
Example:
let str="JavaScript";
const myFun = () => {
console.log(str);
}
myFun();
// Output: JavaScript
Lexical scope means that a function looks up variables in the context where it was defined, and not in the scope immediately around it.
Look at how lexical scope works in Lisp if you want more detail. The selected answer by Kyle Cronin in Dynamic and Lexical variables in Common Lisp is a lot clearer than the answers here.
Coincidentally I only learned about this in a Lisp class, and it happens to apply in JavaScript as well.
I ran this code in Chrome's console.
// JavaScript Equivalent Lisp
var x = 5; //(setf x 5)
console.debug(x); //(print x)
function print_x(){ //(defun print-x ()
console.debug(x); // (print x)
} //)
(function(){ //(let
var x = 10; // ((x 10))
console.debug(x); // (print x)
print_x(); // (print-x)
})(); //)
Output:
5
10
5
Lexical scoping: Variables declared outside of a function are global variables and are visible everywhere in a JavaScript program. Variables declared inside a function have function scope and are visible only to code that appears inside that function.
IBM defines it as:
The portion of a program or segment unit in which a declaration
applies. An identifier declared in a routine is known within that
routine and within all nested routines. If a nested routine declares
an item with the same name, the outer item is not available in the
nested routine.
Example 1:
function x() {
/*
Variable 'a' is only available to function 'x' and function 'y'.
In other words the area defined by 'x' is the lexical scope of
variable 'a'
*/
var a = "I am a";
function y() {
console.log( a )
}
y();
}
// outputs 'I am a'
x();
Example 2:
function x() {
var a = "I am a";
function y() {
/*
If a nested routine declares an item with the same name,
the outer item is not available in the nested routine.
*/
var a = 'I am inner a';
console.log( a )
}
y();
}
// outputs 'I am inner a'
x();
I hope this is helpful, here is my attempt at a slightly more abstract definition:
Lexical scope:
The access or range something (e.g. a function or variable) has to other elements in the program as determined by its position in the source code.
Fwiw, my logic here simply builds from the definitions of:
Lexical: relating to the words or vocabulary of a language (specifically the word as separate from it's grammar or construction) {in our case - a programming language}.
Scope (noun): the range of operation {in our case the range is: what can be accessed}.
Note, the original 1960 definition of Lexical Scope from the ALGOL 60 spec is far more pithy than my attempt above:
Lexical scope: the portion of source code in which a binding of a name with an entity applies. source
Lexical scope refers to the lexicon of identifiers (e.g., variables, functions, etc.) visible from the current position in the execution stack.
- global execution context
- foo
- bar
- function1 execution context
- foo2
- bar2
- function2 execution context
- foo3
- bar3
foo and bar are always within the lexicon of available identifiers because they are global.
When function1 is executed, it has access to a lexicon of foo2, bar2, foo, and bar.
When function2 is executed, it has access to a lexicon of foo3, bar3, foo2, bar2, foo, and bar.
The reason global and/or outer functions do not have access to an inner functions identifiers is because the execution of that function has not occurred yet and therefore, none of its identifiers have been allocated to memory. What’s more, once that inner context executes, it is removed from the execution stack, meaning that all of it’s identifiers have been garbage collected and are no longer available.
Finally, this is why a nested execution context can ALWAYS access it’s ancestors execution context and thus why it has access to a greater lexicon of identifiers.
See:
https://tylermcginnis.com/ultimate-guide-to-execution-contexts-hoisting-scopes-and-closures-in-javascript/
https://developer.mozilla.org/en-US/docs/Glossary/Identifier
Special thanks to #robr3rd for help simplifying the above definition.
There is an important part of the conversation surrounding lexical and dynamic scoping that is missing: a plain explanation of the lifetime of the scoped variable - or when the variable can be accessed.
Dynamic scoping only very loosely corresponds to "global" scoping in the way that we traditionally think about it (the reason I bring up the comparison between the two is that it has already been mentioned - and I don't particularly like the linked article's explanation); it is probably best we don't make the comparison between global and dynamic - though supposedly, according to the linked article, "...[it] is useful as a substitute for globally scoped variables."
So, in plain English, what's the important distinction between the two scoping mechanisms?
Lexical scoping has been defined very well throughout the answers above: lexically scoped variables are available - or, accessible - at the local level of the function in which it was defined.
However - as it is not the focus of the OP - dynamic scoping has not received a great deal of attention and the attention it has received means it probably needs a bit more (that's not a criticism of other answers, but rather a "oh, that answer made we wish there was a bit more"). So, here's a little bit more:
Dynamic scoping means that a variable is accessible to the larger program during the lifetime of the function call - or, while the function is executing. Really, Wikipedia actually does a nice job with the explanation of the difference between the two. So as not to obfuscate it, here is the text that describes dynamic scoping:
...[I]n dynamic scoping (or dynamic scope), if a variable name's scope is a
certain function, then its scope is the time-period during which the
function is executing: while the function is running, the variable
name exists, and is bound to its variable, but after the function
returns, the variable name does not exist.
Ancient question, but here is my take on it.
Lexical (static) scope refers to the scope of a variable in the source code.
In a language like JavaScript, where functions can be passed around and attached and re-attached to miscellaneous objects, you might have though that scope would depend on who’s calling the function at the time, but it doesn’t. Changing the scope that way would be dynamic scope, and JavaScript doesn’t do that, except possibly with the this object reference.
To illustrate the point:
var a='apple';
function doit() {
var a='aardvark';
return function() {
alert(a);
}
}
var test=doit();
test();
In the example, the variable a is defined globally, but shadowed in the doit() function. This function returns another function which, as you see, relies on the a variable outside of its own scope.
If you run this, you will find that the value used is aardvark, not apple which, though it is in the scope of the test() function, is not in the lexical scope of the original function. That is, the scope used is the scope as it appears in the source code, not the scope where the function is actually used.
This fact can have annoying consequences. For example, you might decide that it’s easier to organise your functions separately, and then use them when the time comes, such as in an event handler:
var a='apple',b='banana';
function init() {
var a='aardvark',b='bandicoot';
document.querySelector('button#a').onclick=function(event) {
alert(a);
}
document.querySelector('button#b').onclick=doB;
}
function doB(event) {
alert(b);
}
init();
<button id="a">A</button>
<button id="b">B</button>
This code sample does one of each. You can see that because of lexical scoping, button A uses the inner variable, while button B doesn’t. You may end up nesting functions more than you would have liked.
By the way, in both examples, you will also notice that the inner lexically scoped variables persist even though the containing function function has run its course. This is called closure, and refers to a nested function’s access to outer variables, even if the outer function has finished. JavaScript needs to be smart enough to determine whether those variables are no longer needed, and if not, can garbage collect them.
Here's a different angle on this question that we can get by taking a step back and looking at the role of scoping in the larger framework of interpretation (running a program). In other words, imagine that you were building an interpreter (or compiler) for a language and were responsible for computing the output, given a program and some input to it.
Interpretation involves keeping track of three things:
State - namely, variables and referenced memory locations on the heap and stack.
Operations on that state - namely, every line of code in your program
The environment in which a given operation runs - namely, the projection of state on an operation.
An interpreter starts at the first line of code in a program, computes its environment, runs the line in that environment and captures its effect on the program's state. It then follows the program's control flow to execute the next line of code, and repeats the process till the program ends.
The way you compute the environment for any operation is through a formal set of rules defined by the programming language. The term "binding" is frequently used to describe the mapping of the overall state of the program to a value in the environment. Note that by "overall state" we do not mean global state, but rather the sum total of every reachable definition, at any point in the execution).
This is the framework in which the scoping problem is defined. Now to the next part of what our options are.
As the implementor of the interpreter, you could simplify your task by making the environment as close as possible to the program's state. Accordingly, the environment of a line of code would simply be defined by environment of the previous line of code with the effects of that operation applied to it, regardless of whether the previous line was an assignment, a function call, return from a function, or a control structure such as a while loop.
This is the gist of dynamic scoping, wherein the environment that any code runs in is bound to the state of the program as defined by its execution context.
Or, you could think of a programmer using your language and simplify his or her task of keeping track of the values a variable can take. There are way too many paths and too much complexity involved in reasoning about the outcome the totality of past execution. Lexical Scoping helps do this by restricting the current environment to the portion of state defined in the current block, function or other unit of scope, and its parent (i.e. the block enclosing the current clock, or the function that called the present function).
In other words, with lexical scope the environment that any code sees is bound to state associated with a scope defined explicitly in the language, such as a block or a function.
Scope is the context within which a variable/binding is accessible. Lexical scope means local to the enclosing lexical block or blocks as opposed to for instance global scope.
This topic is strongly related with the built-in bind function and introduced in ECMAScript 6 Arrow Functions. It was really annoying, because for every new "class" (function actually) method we wanted to use, we had to bind this in order to have access to the scope.
JavaScript by default doesn't set its scope of this on functions (it doesn't set the context on this). By default you have to explicitly say which context you want to have.
The arrow functions automatically gets so-called lexical scope (have access to variable's definition in its containing block). When using arrow functions it automatically binds this to the place where the arrow function was defined in the first place, and the context of this arrow functions is its containing block.
See how it works in practice on the simplest examples below.
Before Arrow Functions (no lexical scope by default):
const programming = {
language: "JavaScript",
getLanguage: function() {
return this.language;
}
}
const globalScope = programming.getLanguage;
console.log(globalScope()); // Output: undefined
const localScope = programming.getLanguage.bind(programming);
console.log(localScope()); // Output: "JavaScript"
With arrow functions (lexical scope by default):
const programming = {
language: "JavaScript",
getLanguage: function() {
return this.language;
}
}
const arrowFunction = () => {
console.log(programming.getLanguage());
}
arrowFunction(); // Output: "JavaScript"
Lexical scoping means functions resolve free variables from the scope where they were defined, not from the scope where they are called.
I normally learn by example, and here's a little something:
const lives = 0;
function catCircus () {
this.lives = 1;
const lives = 2;
const cat1 = {
lives: 5,
jumps: () => {
console.log(this.lives);
}
};
cat1.jumps(); // 1
console.log(cat1); // { lives: 5, jumps: [Function: jumps] }
const cat2 = {
lives: 5,
jumps: () => {
console.log(lives);
}
};
cat2.jumps(); // 2
console.log(cat2); // { lives: 5, jumps: [Function: jumps] }
const cat3 = {
lives: 5,
jumps: () => {
const lives = 3;
console.log(lives);
}
};
cat3.jumps(); // 3
console.log(cat3); // { lives: 5, jumps: [Function: jumps] }
const cat4 = {
lives: 5,
jumps: function () {
console.log(lives);
}
};
cat4.jumps(); // 2
console.log(cat4); // { lives: 5, jumps: [Function: jumps] }
const cat5 = {
lives: 5,
jumps: function () {
var lives = 4;
console.log(lives);
}
};
cat5.jumps(); // 4
console.log(cat5); // { lives: 5, jumps: [Function: jumps] }
const cat6 = {
lives: 5,
jumps: function () {
console.log(this.lives);
}
};
cat6.jumps(); // 5
console.log(cat6); // { lives: 5, jumps: [Function: jumps] }
const cat7 = {
lives: 5,
jumps: function thrownOutOfWindow () {
console.log(this.lives);
}
};
cat7.jumps(); // 5
console.log(cat7); // { lives: 5, jumps: [Function: thrownOutOfWindow] }
}
catCircus();

VariableEnvironment's functions

Variable/Lexical Environment component of execution context
Question 1:
For what VariableEnvironment component of exection context is needed?
As said in spec LexicalEnvironment component
used to resolve identifier references made by code
within this execution context.
But VariableEnvironment component used to
holds bindings created by VariableStatements and FunctionDeclarations
within this execution context.
Ok, but evaluation of PrimaryExpression:Identifier is execution with LexicalEnvironment component, not VariableEnvironment of running execution context:
Let env be the running execution context‘s LexicalEnvironment.
If the syntactic production that is being evaluated is contained in a strict mode code, then let strict be true, else let strict be false.
Return the result of calling GetIdentifierReference function passing env, Identifier, and strict as arguments.
Thus is VariableEnvironment need for bindings storage only?
Establishing function context is occuring as:
sec. 10.4.3
If the function code is strict code, set the ThisBinding to thisArg.
Else if thisArg is null or undefined, set the ThisBinding to the global object.
Else if Type(thisArg) is not Object, set the ThisBinding to ToObject(thisArg).
Else set the ThisBinding to thisArg.
Let localEnv be the result of calling NewDeclarativeEnvironment passing the value of the [[Scope]] internal property of F as the
argument.
Set the LexicalEnvironment to localEnv.
Set the VariableEnvironment to localEnv.
Let code be the value of F‘s [[Code]] internal property.
Perform Declaration Binding Instantiation using the function code code and argumentsList as described in 10.5.
Where at step 9 bindings add to a VariableEnvironment only. At step 5 [[Scope]] internal property indicates to outer LexicalEnvironment. Thus i have question
Question 2:
Is it true that just after creation of execution context of function code LexicalEnvironement's initial environment record contains the same bindings that environment record of outer LexicalEnvironment?
Consider the following code snippet into the global code?
Example of function code
function bar(){
var b={b:'b'}
var o={o:'o'}
}
bar();
Question 3:
Is it true that just after creation of bar execution context before the start of execution function code VariableEnvironment's environment record will be contain bar-->function bar(){ ... }, b-->{b:'b'}, o--> {o:'o'}, but LexicalEnvironment's environment record
Question 1
VariableEnvironment is the leaf of the scope chain at the start of a function. Since
all variables and functions are hoisted at the top of the current function (or global scope), it defines the scope of identifiers visible strictly inside a given function.
LexicalEnvironment extends VariableEnvironment when you use the constructs with and catch. See my other answer for more details.
Both environments are used for name resolution. LexicalEnvironment is used most of the time, except in function bodies (i.e. a function within a function), where VariableEnvironment (of the parent function) is supposed to be used instead.
As I said in my previous answer, the case is rather unfrequent and various implementations behave differently.
I'm not sure I understand what you mean by 'binding storage'.
Bindings take place when applicable (i.e parameters passing or assignment) once the names are resolved, whichever environment allowed the resolution.
Basically, the names inside a VariableEnvironment are those of local variables (bound to heap objects when the variables are assigned) and parameters (bound to the passed values when the function is called, as described in steps 8-9 of spec 10.4.3).
The names in LexicalEnvironment will be either the name of the exception context for a catch statement or the names of an object's properties for a with statement. They will be bound to their corresponding instances when the statement is evaluated, and disposed of at the end of the statement body.
For instance:
function stick_to_top (element)
{
with (element.style) { top = 0; }
}
stick_to_top (document.getElementById ("wanderer"));
binding of top will occur when the statement top = 0; is executed, during function invokation.
Name resolution will resolve top as element.top using the Lexical context of stick_to_top() enhanced by the with statement that will contain the names of all element.style properties, and resolve element as stick_to_top()'s argument using the Variable context of stick_to_top(), which contains only the name of the parameter element.
In the end, value 0 will be assigned to property style.top of the DOM object having the ID "wanderer" (assuming getElementById() found it, of course).
Now if you're up for a joke, try this :
var tip = { style:{top:1}};
var top = { style:'', invaluable_information:42};
var tap = { };
stick_to_top (tip);
stick_to_top (top);
console.log ("tip %o top %o", tip, top);
stick_to_top (tap);
result:
tip [object Object] top 0
SCRIPT5007: Object expected
tip behaves just like a regular DOM object since we defined a style.top property for it
tap does not have a style property, so tap.style is undefined and the interpreter throws an error when trying to process the with statement.
top is the unlucky one. It does have a style property so the with statement is happly creating an empty Lexical environment. Now identifier top is nowhere to be found inside stick_to_top(), so name resolution goes back to global context where it happily finds an unsuspecting top variable. Inevitable tragedy ensues...
Question 2
Both Lexical and Variable environments are local to a context. The scope is made of a chain of environments, i.e. when resolving a name, if the identifier could not be found in the current environment, parent environments are tried in succession until you reach the toplevel environment where identifiers are considered properties of the global object.
(since you seem to be interrested mostly in variables, I leave aside the function prototype scope for the sake of concision)
So the answer to your question is no. In your example, the lexical environment of the toplevel is the collection of all global variables (i.e. the properties of the window object), while the lexical environment of foo() is identical to its variable environment, containing only the names of the two locals b and o.
Question 3
It will just contain b-->{b:'b'}, o--> {o:'o'}
bar-->function bar(){ ... } will be in the toplevel's lexical context.
the bar identifier will be a synonym of window.bar.
(here again, think of a JavaScript program being enclosed in an implicit with (window) statement).

JavaScript Scope and Execution Context

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.

Categories

Resources