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

ok this is some code
function myFunc(){
var myvar = 8;
function myFunc2(num){
alert(myvar+num);
}
myFunc2(2);
}
myFunc();
i want to clear my mind so pls correct me if am wrong
i have read allot of articles in stack overflow already but i want to know i understand it well or should i read more.
to my understanding what happens behind the scene is thatin global execution context there it creates function object with the namemyFunc` and its [[scope]] property assigned to global variable object.
and when i call myFunc it creates its own execution context and activation object where all of the function's arguments and function declaration is initialized before any line by line code execution.
when inner function object is created it's internal [[scope]] property is assigned the value of its outer execution context's variable object + global variable object so every function creates its own execution context but before that every function's internal [[scope]] property is assigned first.
i have read allot of articles in stack overflow already but i want to know i understand it well or should i read more.

Here are a couple of pointers based on my understanding of the specification, and based on what sounds unclear on your explanation:
The term "Activation object" was used in ECMAScript 3, but not anymore in the current version of the specification. ES5 uses the term "Lexical Environment" to denote a type (an internal type) consisting of an "Environment Record" value, and possibly a reference to an outer Lexical Environment.
Because of this reference to an outer Lexical Environment, scope can be thought of as a chain. So access to outer scopes (including the global scope) happens through that chain. (When you say that "[[scope]] property is assigned the value of its outer execution context's variable object + global variable object", it sounds like both records are copied into the current function's Lexical Environment, which is not how it happens.)
Hope this helps!

Related

JavaScript Closures - function scope [duplicate]

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

Values of variables in scope when using closure in JavaScript

Can you explain the difference between these 3 pieces of code? They seems identical to me, but the output are different.
1:
var i;
function print(){return function(){console.log(b)}};
function doSetTimeout(b){setTimeout(print(),2000);};
for(i=0;i<10;i++){doSetTimeout(i)}
2:
var i;
function print(){console.log(b)};
function doSetTimeout(b){setTimeout(print,2000);};
for(i=0;i<10;i++){doSetTimeout(i)}
3:
var i;
function doSetTimeout(b){setTimeout(function(){console.log(b)},2000);};
for(i=0;i<10;i++){doSetTimeout(i)}
The first 2 are returning b as undefined, while the 3rd is returning the expected value.
In the first two examples you gave, you aren't passing b into print(), so print has no way to find that variable by looking at its lexical parents.
The closure isn't going to occur when you pass the function value, with print as a parameter, it's going to happen wherever setTimeout() is defined and print() is actually invoked. So you're not getting access to the context you think you are.
In the last example it works anyway, because you are defining the anonymous function inside of a function being executed that already knows what b is, so b is available.
"When a given execution context encounters a function definition in the code, a new function object is created with an internal property named [[scope]] (as in lexical scope) which references the current VariableEnvironment. (ES 5 13.0-2)
Every function gets a [[scope]] property, and when the function is invoked the value of the scope property is assigned to the outer lexical environment reference (or outerLex) property of its VariableEnvironment. (ES 5 10.4.3.5-7) In this way, each VariableEnvironment inherits from the VariableEnvironment of its lexical parent. This scope chaining runs the length of the lexical hierarchy starting from the global object."
Source:
https://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/
Also a good read:
http://davidshariff.com/blog/what-is-the-execution-context-in-javascript/

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

Is 'window' really global in JavaScript?

Take this piece of JavaScript code in a browser:
<script>
console.log(window.someThing);
var x = 12;
function foo() {
window.otherThing = x;
}
</script>
Inside foo we can access window. We all know that, but why exactly?
Is it some kind of special global variable?
Or does the "root scope" (inside the script tag) have it as an implicit local variable and is it simply "closure-inherited" as any other local variable (like x above) can be?
And how does that concur with variables declared directly inside the script tag being set as properties of window? (Or is that not so?)
<script>
var x = 12;
function() {
console.log(window.x);
}
</script>
The reason why you can access "out of scope" or "free" variables in ECMAScript is the so-called scope chain. The scope chain is a special property from each execution context. As mentioned several times before, a context object looks at least like:
[[scope]]
Variable / Activation Object
"this" context value
Each time you access a variable(-name) within a context (a function for instance), the lookup process always starts in its own Activation Object. All formal parameters, function declarations and locally defined variables (var) are stored in that special object. If the variablename was not found in that object, the search goes into the [[Scope]]-chain.
Each time a function(-context) is initialized, it'll copy all parent context variable/activation objects into its internal [[Scope]] property. That is what we call, a lexical scope. That is the reason why closures work in ECMAScript. Since the Global context also has an Variable Object (more precisely, **the variable object for the global object is the global object itself) it also gets copied into the functions [[Scope]] property.
That is the reason why you can access window from within any function :-)
The above explanation has one important conceptional conclusion: Any function in ECMAScript is a closure, which is true. Since every function will at least copy the global context VO in its [[Scope]] property.
Is window really global in JavaScript?
Yes. Unless you create a new variable called window in a narrower scope
function foo() {
var window;
}
Inside foo we can access window, we all know that, but why exactly?
Any function can access variables declared in a wider scope. There is nothing special about window there.
It's all defined in ECMAScript.
The global is a lexical environment that doesn't have an outer lexical environment. All other environments are nested within it, and is bound to a global object with properties specified by the specification.
This places the properties of the global object at the start of the scope chain, from which all other environments inherit.
ES 10.2.3 The Global Environment:
The global environment is a unique Lexical Environment which is created before any ECMAScript code is executed. The global environment’s Environment Record is an object environment record whose binding object is the global object (15.1). The global environment’s outer environment reference is null.
As ECMAScript code is executed, additional properties may be added to the global object and the initial properties may be modified.
ES 15.1 The Global Object
The unique global object is created before control enters any execution context.
Unless otherwise specified, the standard built-in properties of the global object have attributes {[[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}.
The global object does not have a [[Construct]] internal property; it is not possible to use the global object as a constructor with the new operator.
The global object does not have a [[Call]] internal property; it is not possible to invoke the global object as a function.
The values of the [[Prototype]] and [[Class]] internal properties of the global object are implementation-dependent.
In addition to the properties defined in this specification the global object may have additional host defined properties. This may include a property whose value is the global object itself; for example, in the HTML document object model the window property of the global object is the global object itself.
It has to do with the scope chain.
Have a look at the presentation of Nicholas C. Zakas (starting around 5 minutes).
window is the base scope of all JavaScript objects, and it's automatically "attached" to each variables you define, unless you use "var" before the declaration, in this case the scope of the variable it's local (that means that it's contained inside the parent function, or is otherwise global too, if you are declaring your variable outside a function block). Moreover window is defined as a constant*, that is you can't redefine the window object (you will get an error saying "type error: redeclaration of const window").
So:
window.foo = 5;
It's the same as:
var foo = 5;
Or:
function() {
foo = 5;
}
but:
function() {
var foo = 5;
}
In this case, "foo" is local (window.foo === undefined),
The window global scope applies only to the main thread. In web workers there is no window global variable. Instead you have WorkerGlobalScope inside a WebWorker and in a SharedWorkerGlobalScope inside a SharedWorker.
This worker global scope is stored in a variable called self and as MDN describes it:
this scope contains the information usually conveyed by Window objects.
This can become a problem when 3rd party code you are using in your web worker is using the window object. This can be easily solved by declaring a window variable as suggested by #FelipeMicaroniLalli in his answer here like this:
var window = self;
In the book JavaScript: The Good Parts, as I understand, Douglas Crockford explains that window is the global object of the web browser that contains all the global variables. It is like the One Ring...

Activation and Variable Object in JavaScript?

Is the term "activation object" just another name of "variable object" or is there actually any difference between them? I have been reading a few JavaScript articles about how variable scopes are formed in an execution context, and from my point of view it seems that in most of the articles they use these two terms interchangeably.
Well, I just learned something :). From this article, it would appear that within the execution context of a function, the Activation Object is used as the Variable Object:
When an execution context is created a number of things happen in a defined order. First, in the execution context of a function, an "Activation" object is created. [...]
Then the process of "variable instantiation" takes place using an object that ECMA 262 refers to as the "Variable" object. However, the Activation object is used as the Variable object (note this, it is important: they are the same object). Named properties of the Variable object are created for each of the function's formal parameters, and if arguments to the function call correspond with those parameters the values of those arguments are assigned to the properties (otherwise the assigned value is undefined).
However, when you're in the global scope, there isn't an Activation Object, so the Global Object is used as the Variable Object instead:
The global execution context gets some slightly different handling as it does not have arguments so it does not need a defined Activation object to refer to them. [...] The global object is used as the Variable object, which is why globally declared functions become properties of the global object.
So it sounds like "Activation Object" and "Variable Object" are the same thing within a function context, but not within the global context.
An activation object is the uppermost object in a scope-chain with the lowermost being global object.
Whereas variable object is abstract concept and therefore, depending on its execution context, is any link in scope-chain including activation/global object.
It contains:
all the variables and functions you declare inside the function body;
arguments named as specified by the function signature;
arguments as an object named arguments (in case you want your function to support multiple signatures).
It doesn't contain:
this (as it's not a variable);
named function expressions.
Further info - JavaScript. The core.
Few quotes in case of tl;dr:
A variable object is a scope of data related with the execution context. It’s a special object associated with the context and which stores variables and function declarations are being defined within the context.
A variable object is an abstract concept. In different context types, physically, it’s presented using different object.
[..] in the global context the variable object is the global object itself [..]
[..] a function’s variable object is the same simple variable object, but besides variables and function declarations, it also stores formal parameters and arguments object, and is called the activation object.
[..] when accessing this in a code, its value is taken directly from the execution context without any scope-chain lookup.
It's more accurate to say that an Activation object is a type of Variable object. This is similar to how a man is a type of HUMAN. As stated here, the term 'Variable object' is just a GENERALISED term used to describe any object that holds the properties that describe the environment and scope of the currently executing context.
Hence, within the global executing context (i.e., outside of any functions), it ends up being the Global object. Why? Because it’s the object that holds the properties that describe the environment and scope of the global executing context.
Whereas within the function local executing context (i.e., within a function), it is the function local object (a.k.a the Activation object) that is the Variable object, as it's the object that holds the properties that describe the environment and scope of the currently executing function. Properties such as function arguments for example.
An activated object just means an object that represents an element on a web page that an event occurred on. So if an image is clicked, the JavaScript object that represents that image is the activated object.

Categories

Resources