Scope chain in Javascript and calling nested function within the global scope - javascript

Here is the example I want to be enlighten on (Something that doesn't actually works).
var myVar = 2;
function a(){
var myVar = 2;
function b(){
console.log(myVar);
}
};
a();
b();
This will output in the console: Uncaught ReferenceError: b is not defined.
As you can see I have a function named a with a nested function called b.
At first I thought I could invoke b outside a and get it working normally.
I thought that would work because at first I call the a function.
By doing that I had in mind the fact that the a function would be put on the execution stack and during its creation phase the b function defined inside would be set in the memory.
As this is in memory I thought I could then execute this outside the function. Which obviously doesn't work.
So my conclusion is the b function is indeed set into memory during the creation phase of the a function but once the a function has finished to execute, once it's popped of the execution stack, the b function gets popped off the memory at the same time.
Thus calling it (I mean the b function) within the global scope is impossible.
Am I right on this ?

You are complicating things unnecessarily by speaking about execution stacks, creation phases and such.
The explanation is very simple: you cannot call b because the spec says that b is out of scope at the site where you are trying to call it. That is all, end of story.
Your example would actually work if converted to PHP, which makes me think that perhaps this is where you got the idea from. But JS and PHP are different languages and the (IMO ridiculous) manner that PHP treats nested functions does not transfer over.

If you want to call b outside of a, you need to create a reference to it outside of a:
var myVar = 2;
function a(){
var myVar = 2;
function b(){
console.log(myVar);
}
return b;
};
var b = a();
b();
This however won't cause b to print the global myVar. It will still have access to the myVar inside the closure scope of a.

Related

Why execution context of function B doesnt pass its activation-object into function A-s scope-chain-object, that A has acces to variables of B

Hy guys thanks for reading my question. So I am researching this problem since 2 days and didnt find any answer, so thanks for helping. So here is the below code:
function A(){
console.log(myVar);
}
function B(){
var myVar = 2;
A();
}
B();
So here if I run this code, from function A will get an error massage: "myVar is not defined", because it doesnt have access to the variables of function B and this is what I dont udnerstand.
So as far as I know when the code starts to run, the global execution context will be created by the javascript engine and each time the engine hits a parentheses for function call - and some other conditions are met- , javascript creates an execution context object for the function which has been called.
It should include and the scope chain, the activation object and the "this" keyword and In the scope chain should be all the variable/activation objects of the parent execution contexts
So with otherwords function A in its scope-chain-object should have function B-s all variables (but obviously it is not the case and this is what I dont understand).
But if I run this code, where function A-s definition is nested in function B:
function B(){
var myVar = 2;
A();
function A(){
console.log(myVar);
}
}
B();
So now function A will have access to the variables declaired and initialized in function B.
But in my head it shouldnt matter, where function A have been defined since it has been called in the context of function B.
Even when the this keywords value is defined in the creation phase, its value will based on, where and how the function is called, not where it has been defined.
Thanks guys that your read threw my tons of words, I really appriciate it.
And thanks for every answer or any kind of article or matterial, that could help me understand this anomaly.
Cheers and thanks a lot.
In JavaScript a Lexical Environment of a function is called lexical because it is determined by the static structure of a program, not where the function is called from. It means that the outer Lexical Environment of the function A() will be the environment within which the function A() is declared, not called.

Javascript Call Stack / Execution Context reference

When I executed the following javascript, I was expecting b()'s console log to print undefined. (Since I did not declare name).
function b(){
console.log(name);
}
function a(){
var name = "rupesh";
b();
}
var name = "Demo";
a();
Expected Output: Undefined
Actual output: Demo
I've been reading on Global execution context, Execution context of Javascript. It's been mentioned that the execution context will look for Global execution context.
But if i understand right, function a() and function b() are executed in a stack. How does it go back to execution context (In datastructure perspective this doesn't happen).
Kinda confused. Please explain how this works!
When I executed the following javascript, I was expecting b()'s console log to print undefined. (Since I did not declare name).
Technically name is declared. That's so called hoisting. So, the runtimer "catch" all the var declarations and put them on top of the function (in your case, as it's not inside a function, they're attached to the global namespace). So, it'd be like this:
var name;
function b(){
console.log(name);
}
...
Now, when a() is called the name variable has value assigned, in this case "Demo".
Inside function a () {...} you assign a variable called name again, but as this has var before it, that name doesn't change the global name (I think you have already figured that out, since you'd expected name to be undefined).
Finally, when b() is invoked inside a(), it looks to the global name variable assigned with the "Demo" value.
Just to show the whole picture, that's how the runtime "sees" your code:
var name;
function b(){
console.log(name);
}
function a(){
var name = "rupesh";
b();
}
name = "Demo";
a();

Understanding javascript hoisting and execution context

b();
console.log(a);
var a = 'Hello World';
function b(){
console.log('Called b!');
}
I have read about the term "hoisting", but it isn't pretty clear to me. Why does the function gets executed while the variable is set to undefined?
The interesting part is, the variable didn't show any error. But it showed undefined. But when I remove the variable totally, then it shows an error. That means, the variable is present somewhere though. right?
But if it is present, then why can't the compiler compile it and can compile the function here?
I know that var a is getting hoisted. I want to know why the engine is treating the variable and the function in a different way that is what's happening behind the scenes during the execution context.
Any detailed explanation would be helpful about how the engine is creating the execution context.
In this question I'm asking about how javascript engine is behaving differently with the function and the variable. And what is exactly happening in the creating state and execution state of the execution phase. So, it's not a duplicate question.
But if it is present, then why can't the compiler compile it and can compile the function here?
Basically it boils down to whether the value of the binding can be determined without executing the code or not.
The function declaration itself doesn't depend on runtime information. Keep in mind that the body is not evaluated until the function is called. So even without really executing the code, its clear that the value of b is a function.
However, the initialization value of a variable declaration may depend on runtime information. Consider this:
var a = 10 + bar();
There is no way for the engine to "hoist" the initialization value without evaluating the expression (and executing bar in the process).
Of course in your example, the initialization value ('Hello World') is static as well, so it could be hoisted. But then the behavior would be inconsistent and probably more confusing.
What exactly happens when control enters a new function is defined in the spec. There you can see how variable declarations and function declarations are treated.
With hoisting, this is what your code looks like
function b(){
console.log('Called b!');
}
var a;
b();
console.log(a);
a = 'Hello World';
As you can see, a is declared at the the top, but has not been set to a value yet. That is why you get undefined when you log that variable.
If you remove the a variable altogether, you get the Uncaught ReferenceError because a has not been declared.
The above code is same as below
var a;
function b(){
console.log('Called b!');
}
b();
console.log(a);
a = 'Hello World';
Explanation - Function along with its definition are hoisted to the top. Variable declaration is hoisted not its definition
var a; is hoisted. a = 'Hello World!'; is not hoisted. It's that simple.

Javascript - outer reference of a function shows "not defined"

i have the following code:
function log(a) {
var b = 5;
a();
}
log(function(){
console.log(b);
});
When that anon function is executed at function log, I am getting "b is not defined". Well, It seems like that anon's outer environment reference isn't log's, as If it wasn't created inside of it so therefore it can't find that var. so where is it being created? on the global level? My initial thought was that those parentheses make the anon function created inside of log's.
Every time you call a function, assuming that you do not declare global variables (you didn't declared any), the scope is created for that function and what goes in that scope is determined not by where the function was called but by where it was defined. You can see that where you defined the anonymous function (in the call to log), the variable b is not in that scope that is why it's not available.
Let's rewrite your code:
function log(a) {
var b = 5;
a();
}
function logger() {
console.log(b);
}
log(logger);
You can see that your code and mine are doing the same thing, the only difference is that mine code doesn't have an anon function. They do not share common variables in their scopes.
Now check this out:
var b = 5;
function log(a) {
a();
}
function logger() {
console.log(b);
}
log(logger);
Now both log and logger share a common variable b in their scopes (log is not using b so if you check it in a debugger it will be undefined). As I say you don't determine scope by where function was called but by where and how it was declared.
In JavaScript scopes exists within functions. So your b variable is visible only within its scope - the anonymous function. If you want it to be visible outside the function then you can assign the variable to the global scope.
function log(a) {
window.b = 5;
a();
}
log(function(){
console.log(b);
});

Javascript Scope/Closure: Why can I access internal vars here?

I am currently working on a relatively simple project and discovered something:
var test = (function() {
var internal = 5;
return {
init: function() {
$(document).on('click', function() {
alert(internal);
});
}
};
}());
test.init();
I thought closure and javascript scope (as I understood it) meant that a function can only access its own variables, and those 1 level above it. So Why does this work? When I click on the document I get an alert of "5", I expected to get undefined.
Here is a JSFiddle showing what I'm doing:
http://jsfiddle.net/mcraig_brs/m644L/1/
I thought closure and javascript scope (as I understood it) meant that a function can only access its own variables, and those 1 level above it.
Nope, it's all levels above it. In fact, that's how global variables work in JavaScript; they're just an example of closures in action.
So Why does this work?
When the JavaScript engine needs to resolve a symbol, it looks first (loosely) in the execution context that the symbol appears in (in this case, the one created by the call to the anonymous function you're passing into on). If it doesn't find a matching variable there, it looks at the execution context that surrounds that one (in this case, the one created by calling init). If it doesn't find it there, it looks at the next one out (the one created by calling your outermost anonymous function). And if not there, the next level out, until it reaches the global execution context.
More about closures (on my blog): Closures are not complicated
Note that I kept saying "...created by the call to..." above. This is a critical point: There can be (almost always are) multiple execution contexts created for a given scope as a program runs. Consider:
function foo(name) {
return function() {
alert(name);
};
}
(This is only two levels again, but it applies to as many levels as you like.)
foo, when called, creates and returns a function that, when called, shows us the name that was passed into foo when that function was created:
var f1 = foo("one");
var f2 = foo("two");
f1(); // "one"
f2(); // "two"
Calling foo creates an execution context. The function foo creates has an enduring reference to the part of that context that contains variables for that call (the spec calls it the "variable binding object"). That binding object still exists after foo returns, which is why when we call the function foo creates, it still has access to the relevant name variable.
It's important to remember that it isn't that closures get a copy of the value of the variable. They get an enduring reference to that variable. Which is why this works:
function foo(a) {
return function() {
alert(++a);
};
}
var f = foo(0);
f(); // 1
f(); // 2
f(); // 3
Javascript is statically scoped. when you are writing a function, you will have access to all the variables available to you inside the function as they are available from where you are accessing it.
var a = 10;
function foo() {
// now i have access in a
var b = 20;
// i have access to both a and b
function bar() {
// still have access to both a and b
var c = 30;
// any more nested function will have access to a,b and c
}
}

Categories

Resources