Function declaration under the hood - javascript

const var1 = 8;
const var2 = 9;
function func1(){
console.log("Inside func1")
}
func1();
When above programme will be executed a global execution will be created Inside Global execution two variables var1 and var2 will be created during the creation phase of global execution context and values 8, 9 will be assigned inside these variables during execution phase of global execution context
so my question is what will happen with function identifier func1.What will be stored inside a variable name
func1 in memory when it get declared in global phase. Also how function declaration works under the hood how and where function are stored in memory`

When the above program is executed, during the creation phase of the global execution context, the function identifier func1 will be hoisted to the top of the scope, and a reference to the function object will be stored in memory. This means that the func1 variable will be assigned a reference to the function object even before the function is declared, and it can be called from anywhere in the code.
The function declaration works by creating a function object that consists of the function code and a reference to the surrounding scope. This function object is stored in memory in a specific location, and the function identifier is assigned a reference to that location. When the function is called, a new execution context is created, and the function code is executed in that context.
It's important to note that function expressions, as opposed to function declarations, are not hoisted to the top of the scope, and their identifiers are only available within the scope of the expression itself.

Related

How can javascript have lexical scope if scope is assigned at runtime?

Im confused about javascript having lexical scope.
Lexical scope: Lexical scoping means whatever variables are in scope where you define a function from (as opposed to when you call it) are in scope in the function.
However in JS its: scope isn't assigned when the function is defined and compiled rather it's assigned at runtime i.e. when the function is called
In the below example: If JS had lexical scope, I would get an error. However I do not because of hoisting and at run time js engine checks for x.
function f() {
console.log(x);
}
const x = 10;
f(); // 10
Can someone explain with an example how JS can have lexical scope? Thanks!
However in JS its: scope isn't assigned when the function is defined and compiled rather it's assigned at runtime i.e. when the function is called
I think you are confusing yourself with this description of scope in JS. A more accurate description of scope in JS is given by this article (emphasis added):
Because functions are also defined at this time (lexing phase), we can say that lexical scope is based on where variables and blocks of scope exist at author time, and thus are locked down at the end of the lexing phase. Scope is not defined at runtime, rather it can be accessed at runtime.
So, in your example:
function f() {
console.log(x);
}
const x = 10;
f(); // 10
What is happening is that the scope chain of function f consists of:
its local scope
the outer, global scope
and this "scope chain" is defined at author time (i.e. lexical scope).
At author time, the constant x is defined within the global scope, and when f is called, x is available within the global scope. That x is not defined when the function f is declared (but NOT called) is irrelevant for this discussion.
Also, you are incorrect when you mention "hoisting" regarding your code example: variables declared with const are NOT hoisted.
If we alter your example, we will get a Reference Error, since the constant x has not been initialized in the global scope (i.e. on author time), when the function f is called (and function f looks through its scope chain, which has been defined on author time):
function f() {
console.log(x);
}
f(); // 10
const x = 10;
See below example, everything outside function f is compiled and vars are hoisted.
But the contents inside function f are not hoisted/parsed until it's called. And the local variables inside f remain accessible within the function (i.e. the lexical scope of function).
function f() {
console.log(x);
var a = 20;
}
const x = 10;
f(); // 10
console.log(a);

Do JS variables have a scope if the function that declares them is never called?

In this code, how many variables are in the global scope, and how many are in the local scope of the greet function?
var foo = 42;
var bar = 43;
function greet(name) {
greeting = 'Hello';
return greeting + ' ' + name;
}
I believe there are two global variables (foo and bar) and 0 local variables. Since the function never gets called, name and greeting don't get declared so I would say that they are not in the global or local scope.
What do you think? Can greeting and name have a scope if the function greet() is never invoked?
This is somewhat of a theoretical question along the lines of "if a tree falls in the forest...".
The answer depends on whether you are analyzing the problem from a static lexical perspective vs the dynamic execution environment. For the latter, your analysis is accurate, although. If the code above is executed, there will be three identifiers defined in the global space, the two vars and the function. The greeting var and name argument will not "come into existence".
That said, if I were in a code review evaluating this statically, I would have to ask "well isn't there a purpose to defining the function greet"? The assumption must be that it is eventually intended to be called - otherwise why write it (or for that matter, any of the code above). And as such, the use of that function would definitely introduce a global variable.
Source - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
The scope of a variable declared with var is its current execution
context, which is either the enclosing function or, for variables
declared outside any function, global.
The variables foo and bar are declared at the top. So they will be assigned directly to the window object (global scope).
Assigning a value to an undeclared variable implicitly creates it as a
global variable (it becomes a property of the global object) when the
assignment is executed.
Undeclared variables do not exist until the code assigning to them is
executed.
The variable greeting is not declared and is present within the function greet which is not called. So, this will not create the variable greeting until the function is called and if called it will create greeting as a global variable.
name is not a variable, it's a parameter and acts like a placeholder.
In short, there are two global variables - foo and bar and if function greet is invoked, then there will be three global variables foo, bar and greeting.
Can greeting and name have a scope if the function greet() is never invoked?
Yes, name exists already in the local scope as although the function wasn't executed yet, it was still parsed.
greeting however will only exist when the function gets called, but wether its in the global scope is not relevant as its just bad practice to have implicit globals.

What is the difference and relationship between execution context and lexical environment?

In JavaScript: Understanding the Weird Parts lexical environment is explained as the scope of your code while execution context is a collection of lexical environments, and that it includes stuff beyond your written code.
The descriptions of these terms still sound overlapping in functionality and it's unclear as to what execution context does or how it does it.
The best way to think of an execution context is as a stack frame, while lexical environments are indeed the scopes.
The respective spec chapters (§8.1 Lexical Environments and §8.3 Execution Contexts) explain:
Execution contexts contain the current evaluation state of code, a reference to the code (function) itself, and possibly references to the current lexical environments.
Execution contexts are managed in a stack.
Lexical environments contain an environment record in which the variables are stored, and a reference to their parent environment (if any).
Lexical environments build a tree structure.
With every change of the execution context, the lexical environment changes as well. However the lexical environment may change independently from that as well, for example when entering a block.
Execution Context & Execution Context stack : Execution context is the internal javascript construct to track execution of a function or the global code. The js engine maintains a stack - execution context stack or call stack, which contains these contexts and the global execution context stays at the bottom of this stack. And a new execution context is created and pushed to the stack when execution of a function begins. A particular execution context tracks the pointer where statement of the corresponding function is being executed. An execution context is popped from the stack when corresponding function's execution is finished.
Lexical Environment : it's the internal js engine construct that holds identifier-variable mapping. (here identifier refers to the name of variables/functions, and variable is the reference to actual object [including function type object] or primitive value). A lexical environment also holds a reference to a parent lexical environment.
Now, for every execution context -- 1) a corresponding lexical environment is created and 2) if any function is created in that execution context, reference to that lexical environment is stored at the internal property ( [[Environment]] ) of that function. So, every function tracks the lexical environment related to the execution context it was created in.
And every lexical environment tracks its parent lexical environment (that of parent execution context). As a result, every function has a chain of lexical environments attached to it. [Note: in js a function is an object, creating a function by a statement means creating an object of type Function. So like other objects, a function can hold properties both internal and user defined]
The js engine search any variable or function identifier in the current lexical environment, if not found it searches the chain attached to the enclosing function. (for global code this chain does not exist). So, you understand how scoping of variables and functions are maintained. The concept of closure is also backed by, this chain (not a standard term, I just used it to ease the understanding). When a function instance is passed to another function as an argument, to be used as callback, it carries it's chain with it (sort of).
Note: the answer is based on what I learned from 'Secrets of the Javascript Ninja, 2/e'
The answer marked above likened the Execution Context to a Stack Frame. But the Execution Context in JavaScript is no ordinary Stack Frame.
In the global Execution Context, JavaScript Engine creates two things for you, a Global Object (an Object is a collection of name/value pairs) and a special variable called 'this'. In browsers, the Global Object is a window object. In NodeJS, the global object is something else. The point is there is always a global object.
When you create variables and functions that are not inside other functions, those variables are in the global context and thus get attached to the global object, which in the case of browsers is the window object.
hello = 'hello world'
> "hello world"
window.hello
> "hello world"
The execution context in JavaScript is created in two phases. The first phase is the Creation Phase. In the global execution context, the Global Object is setup and in memory, the special variable 'this' is setup, points to Global Object and is in memory, and there is an Outer Environment (Lexical Environment). As the Parser begins the Creation Phase of the execution context, it first recognizes where you created variables and functions. So the Parser sets up memory space for variables and functions. This step is called 'Hoisting'. Hence, before your specific code is executed line by line, the JavaScript Engine already set aside memory space for the variables and functions you created in the global Execution Context:
console.log(a);
console.log(b());
console.log(d);
var a = 'a';
function b(){
return 'called from b';
}
function c(){
d = 'd';
}
> undefined
> called from b
> Uncaught ReferenceError: d is not defined
In the above example, since the variable 'a' and the function b() were created in the global Execution Context, memory space is allocated for them. Note though that the variables are not initialized, just declared with an undefined value. This is not the case for functions. Functions are both declared and initialized, so both the identifier and the actual code of the function is stored in memory. Also note that since d (even though it is not specified with var, let or const) is not in the global Execution Context, no memory space is allocated for it. And so an exception is raised when we try to access the d identifier.
Now if we invoke c() before we reference the d variable, then a new execution context is evaluated (which is not the global Execution Context) and then d will be in memory (in that new execution context, the this keyword will point to the global object since we did not place 'new' before the function invocation and so d will be attached to the global object):
console.log(a);
console.log(b);
console.log(c());
console.log(d);
var a = 'a';
function b(){
return 'called from b';
}
function c(){
d = 'd';
return 'called from c';
}
> undefined
> b() { return 'called from b' }
> called from c
> d
One final point about the Creation Phase of the Execution Context. Since 'hoisting' occurs, order of function definitions or variables do not matter in terms of lexical scoping.
The second phase of the Execution Context is called the Execution Phase, and this is where assignments occur. The JavaScript engine begins parsing your code. So that is when variables will be assigned a value. In the first phase, they were just declared and stored in memory with an undefined value. 'undefined' is a placeholder which is JavaScript's way of saying 'I don't know what this value is yet'. This is the same placeholder JavaScript gives when you declare a variable without assigning it a value. Consequently, it is not a good idea to rely on JavaScript's 'Hoisting' feature. Simply put, do not use a variable in global Execution Context (or in any execution context) before it is declared with var, const or let. So it is always better to do this:
var a = 'a';
function b(){
return 'called from b';
}
console.log(a);
console.log(b());
Do not confuse yourself with the JavaScript built-in data type 'undefined' vs an undefined exception raised by the parser. When a variable is not declared anywhere and you try to use it, the JavaScript Engine will raise an exception 'Uncaught ReferenceError: [variable] is not defined'. JavaScript is saying that the variable is not in memory. This is different then initializing a variable with the undefined data type.
In addition to the global Execution Context, function invocation creates a new Execution Context. First, in the below example, a global Execution Context is created. The Creation Phase of the global Execution Context will be handled by the JavaScript Engine. It will create a Global Object (window in the case of browsers), and it will create a special variable 'this' and point it to the Global Object. Then the b and a function will be attached to the Global Object. Memory space will be allocated for them, and since they are functions, their code will be stored in memory as well. If there were any variables, they will be stored in memory too, but they will not be initialized and thus stored with the data type undefined. Then the Execution Phase begins. Since JavaScript is single-threaded, it executes line by line. During this time, it encounters a(). It sees the '()' and knows it must invoke the function a. A new Execution Context is created and placed on the Execution Stack. As you probably know, the stack data structure is last in first out. An Execution Context is pushed onto the Execution Stack, and when it is finished, it is popped from the stack. Whatever context is on top, that is the Execution Context that is currently running.
function b(){
}
function a(){
b();
}
a();
The a() Execution Context will be stacked on top of the global Execution Context. It will have its own memory space for local variables and functions. It will go through the Creation Phase and Execution Phase of the Execution Context. During a() Execution Context's Creation Phase, since it did not declare any variables or functions, it does not allocate space for any new variables or functions. If it did declare any local variables or functions, it will go through the same 'Hoisting' process as is the case in the global Execution Context. Also, a new special 'this' variable is created for that particular function. Note though if you invoke the function without the new keyword, then 'this' will still reference to the global object, which is the window object in browsers.
Then, it moves on to the Execution Phase. Here it invokes the b() function, and now a third Execution Context is created. This is the b() Execution Context. It goes through the same Creation and Execution Phase as the other Execution Contexts'.
When b() finishes, it is popped off the stack, and then when a() finishes, it will be popped off the stack, and then we return back to the global Execution Stack. Importantly, each execution context stores a pointer to where it left off when it invoked a function and hence created a new execution context. So when b() finishes, a() returns to the statement wherein it invoked b(). And then continues execution on the next statement in that execution context. Again, remember, JavaScript is single-threaded, so it executes line by line.
The key about the Lexical Environment is it has a link to any Outer Environment (i.e. its scope chain), so it is used to resolve identifiers outside the current Execution Context. Ultimately, a corresponding Lexical Environment is created for every Execution Context. The Lexical Environment cares about where the code sits physically (lexically) in your application.
Execution Context
Execution Context is created every time, the JS engine calls a function. They stays in the call stack.
Lexical Environment
The lexical environment includes the scopes that are present at a certain point in time. Every execution context has its own lexical environment.
Check the image and see the scope and the call stack section on the right side of the image:
The call Stack section contains two execution context (test1 and anonymous).
The scope section contains the lexical environment of the test1 execution context.
test1 lexical environment has three objects Global, Local, and Block when the JS engine is executing line no 10.

Execution Stack vs Scope Chain

function one() {
function two() {
alert(i);
}
return two;
}
(function() {
var i = 3;
var f = one();
f(); // Uncaught ReferenceError: i is not defined
}());
The articles I've read say that, when a function is called, a new execution context is added on to the stack and the scope chain is created by traversing up the stack. But surely that would result in 3 being alerted in the above code?
How does it work out the scope chain?
The scope chain is determined by the lexical nesting of scopes. The scope can be affected dynamically (via with), but that causes a lot of problems. It's definitely not the case that the current stack of function activations has anything to do with scope.
When you do var i = 3;, you are creating a local variable that exists only in the scope of the immediately-invoked function expression (IIFE).
Any functions that are defined in that scope can access the variable i.
one() (and therefore also two()) was declared outside the scope, so it has no idea what i is. It's looking up its scope chain to window.i, which doesn't exist.
The call stack (as mentioned keeps adding an execution context to the top of the stack when a function is invoked) and lexical scope (which allows access to variables from outer scope) are independent of each other.
Lexical scope depends only on where the function is created not where the function is invoked, so in your example function "two" is created inside function "one", so when variable "i" inside function "two" tries to access "i", it tries to find "i" in its own scope first, since there is no "i" defined it will go out to the scope where the function is created in your case its function "one" (not where the function is invoked in anonymous IIFE below) and it couldn't find variable "i" again inside function "one", now since function "one" is defined inside global scope (the default execution context) JS will try to find the value of "i" inside the global scope which results in "undefined".
In order to access variable "i" you need to move function "two" into anonymous IIFE as shown below, function two has outer lexical scope of function "one" which has an outer lexical scope of anonymous IIFE which has i assigned to 3 which is alerted.
(function () {
var i = 3;
function one() {
function two() {
alert(i); // will alert 3
}
return two;
}
var f = one();
f();
}());
Hope this is clear now :)
The call stack and the execution context stack are not the same. A function call adds a level to the call stack, but execution context stacks are not changed. However, the function that you call has a different execution context stack.
Each function scope has its own execution context stack which is determined by where the function is created, it doesn't inherit the execution context stack from the calling code.
If you nest functions in each other and only call the inner functions, like in the first example on the page, the call stack and the execution context stack will happen to correspond.
Execution stack is what happens on hardware (memory), regardless of whatever high level language is running. The scope chain model is managed by specific interpreter to implement programming language features such as functional programming, which itself is another program independent from the one you've written, the sequence of function call stacks via the interpreter is different from the actual order on physical hardware.

javascript function internal scope [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Consider the following code:
function nepaliBuddha() {
var a = 20;
return function buddhaNepal() {
console.log(a);
}
}
var closure = nepaliBuddha();
closure(); // logs 20
Now when we invoke closure output is 20. This proves that the internal scope property ([[scope]]) was assigned to the inner function where it was defined or say when declared.If this wasn't assigned at declaration ,there was no way to log 20 as it gets invoked in different context
Invoking closure() the scope chain of a function context is created at function call and consists of the activation object or VO of the current context and the internal [[scope]] property of this function.
Invocation also creates [[scope]] property , this means that internal scope property is created at declaration as well as at execution isn't it?
Usually the definition says the [[scope]] property gets created at run time or at function call but this isn't true as [[scope]] property is already assigned at declaration as well.
What I think is the [[scope]] property might get updated after execution of function, is it? Please give clear definition of [[scope]] internal property. How and when it is created at declaration time or at execution time or at both time.
Wow, aren't you thoroughly confused. Alright, I'll try to explain closures as simply as possible.
First, we'll start with scopes. There are two types of scopes:
Block scopes
Function scopes
A block scope begins immediately when it occurs in the program. A function scope on the other hand does not begin until the function is called. Hence multiple calls to the same function result in multiple scopes being created.
JavaScript does not have block scopes. It only has function scopes. Hence to emulate a block scope we need to create a function expression and immediately execute it. This patttern is called an immediately invoked function expression (IIFE) and it looks like this:
(function () {
// this is the JS equivalent of a block scope
}());
Beside block scopes and function scopes there's another way to classify scopes. Hence we also have:
Lexical scopes
Dynamic scopes
This distinction only applies to function scopes because block scopes are always lexically scoped. JavaScript only has lexical scopes.
To understand the difference between lexical scopes and dynamic scopes we need to understand the difference between free and bound variables.
A free variable is a variable which is used within a function but which is not declared within that function.
A variable which is declared within a function is said to be bound to that function.
Consider the following program:
function add(x, y) {
return x + y; // x and y are bound to add
}
In the above program the variables x and y are bound to the function add because they are declared within add.
On the other hand the variables x and y in the following program are free within the function add because they are not declared within add but they are used within add:
function add() {
return x + y; // x and y are free within add
}
Now free variables are a problem. They need to be mapped to some value, but which value? This is where lexical and dynamic scopes come into picture. I won't go into the major details, but you can read about it on Wikipedia.
Scopes are a lot like prototypal inheritance. When a new scope begins it inherits from a parent scope forming a chain of scopes much like prototype chains in JavaScript.
Lexical scopes and dynamic scopes differ with respect to which parent scope a new scope inherits form.
In lexical scoping a new function scope inherits from the scope in which that function was defined (i.e. its lexical environment).
In dynamic scoping a new function scope inherits from the scope in which that function was called (i.e. the calling scope).
Since JavaScript only has lexical scoping we won't bother with dynamic scoping. Consider the following program:
var count = 0;
function incrementCount() {
return ++count;
}
(function () {
var count = 100;
alert(incrementCount()); // 1
}());
Here the function incrementCounter has one free variable - count. Since JavaScript has lexical scoping count will be mapped to the global variable count instead of the local count declared within the IIFE. Hence incrementCount returns 1 and not 101.
Now closures only work in languages which have lexical scoping. Consider the following program:
function getCounter() {
var count = 0;
return function () {
return ++count;
};
}
var counter = getCounter();
alert(counter()); // 1
alert(counter()); // 2
alert(counter()); // 3
In the above program the function returned by getCounter is a closure with respect to the variable count because:
The variable count is free within the returned function (i.e. counter).
The function is moved outside of the scope within which count is declared.
Both these conditions are necessary for a function to be called a closure. For more information read the following answer: https://stackoverflow.com/a/12931785/783743
Now the important thing to understand here is that the function counter will still be called a closure even though it may never be invoked. A closure is simply a function which closes over a variable (which is called the upvalue of the closure).
When we invoke getCounter we create a new scope (let's call this scope A), and each time we invoke the function returned by getCounter (i.e. counter) we create a new scope which inherits from scope A. That's all. No new closure is created.
A closure is a special kind of object that combines two things: a function, and the environment in which that function was created. The environment consists of any local variables that were in-scope at the time that the closure was created.
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
Now call makeFunc()
var myFunc = makeFunc();
myFunc();
In this case, myFunc is a closure that incorporates both the displayName function and the "Mozilla" string that existed when the closure was created, MDN.
So, the scope created exactly when I called var myFunc = makeFunc(); and myFunc() (the result of the makeFunc() call) is now a closure. So, go to the first line where
A closure is a special kind of object that combines two things: a
function, and the environment in which that function was created.
Now consider these
function nepaliBuddha() {
var a = 1;
return function buddhaNepal() {
a = a+1;
console.log(a);
}
}
var closure1 = nepaliBuddha(); // An individual scope
var closure2 = nepaliBuddha(); // An individual scope
closure1(); // 1
closure1(); // 2
closure2(); // 1
closure2(); // 2
closure2(); // 3
Demo.
Which means, closure1() and closure2() are closures and both have their personal scope/environment and they have access to their own scope once they get it (in this case, every time you call nepaliBuddha you are creating a closure and giving/saving it to a variable).
Scope defines the area, where functions, variables and such are available. So, when you defined/declared the function buddhaNepal (inner function) inside the nepaliBuddha (outer function) the buddhaNepal (inner function) has been just separated from the global scope and nothing else. It can't access anything in the global scope but it has it's own scope, that's it. The nepaliBuddha (outer function) is the boundary of the buddhaNepal (inner function) and in this case the nepaliBuddha outer function's local scope/environment is the global scope for the buddhaNepal (inner function).
in JavaScript, this is known as Lexical Scopeing it defines how variable names are resolved in nested functions. Other names of Lexical Scope are Static Scoping or Closure. It means that the scope of an inner function contains the scope of a parent function.

Categories