JavaScript Closure in Chrome - javascript

There is the following code
function fn1 () {
const a = 1;
const b = 2;
const c = 3;
function fn2() {
console.log("xx");
}
function fn3() {
console.log(a);
console.log(c);
}
return fn2;
}
const clo = fn1();
console.dir(clo);
When I was run this code in Chrome Console, I got this:
I know fn3 references the variable of fn1, but I just return the fn2, why there is a closure in fn2 [[Scopes]]?
Hope that people who know this reason to give some advice! thank you.

Both fn2 and fn3 are created within fn1, so both are closures over (have a reference to) the lexical environment object created for the call to fn1. (The lexical environment object is what holds the bindings for a, b, c, and a few other things.) That's true whether they use that link (like fn3 does, by accessing fn1's local variables) or not (fn2).
Some JavaScript engines have experimented with optimizing that away when possible: removing a function's link to the environment where it was created (linking it directly to the outer environment instead). IIRC, V8 (in Chrome) did experiment with doing that, but found that in most cases the runtime cost of doing that analysis was more expensive than just letting the closure remain, and so didn't carry that work forward when they replaced the internals of the engine a few years back.
Separately, some engines have experimented with optimizing the content of closures — removing the bindings from the lexical environment object that aren't used by any of the functions closing over it. From your screenshot, it looks like V8 does still do that part, at least in trivial cases like that one, since only the bindings that fn3 uses are listed (a and c, not b). At a specification level, all of those bindings would be retained (not that we could tell in our code), but engines are free to optimize where the optimization doesn't lead to out-of-specification behavior.

When you are returning fn2 a closure is created that makes all the available variables in the outer scope available.
JS doesn't check if you actually use those variables, they are added to the closure none the less.

Related

Why visual studio code call Closure objects that aren't a closure

During some tries with the debugger in javascript (Node.js), I surprised that VSCode call "Closure" objects that are not an "Abstract Closure" (in terms of https://tc39.es/ecma262/#sec-abstract-closure).
I'm wondering why VSCode debugger shows to me that name.
If I understood correctly from the ecma, that are the lexical scope not the closure itself.
function outer () {
const a = "some text";
function middle() {
const b = "other text"
return function inner() {
console.log(a, b)
}
}
const x = middle()
return x // line where the debugger says "Closure"
}
const c = outer();
c()
The section you've linked to isn't defining the term "closure" in its general sense, it's defining the specification term "Abstract Closure:"
The Abstract Closure specification type is used to refer to algorithm steps together with a collection of values.
That's a closure, but not the only kind that can exist, and it's just a mechanism for explaining things in the specification.
VS Code is using the term "closure," not Abstract Closure. All functions in JavaScript are closures: Whenever a function is created, it gets a link to the environment record that the function closed over (the link is called [[Environment]] in the spec). When resolving references to bindings (loosely, "variables") within the function code, that link is used (and its link to its outer environment, etc.) to find the relevant binding.
What VS Code is telling you is that the function x refers to closes over the environment for the call to middle, which in turn closes over the call to outer, which in turn closes over the global environment. (And it's also showing the contents of those environments, which is handy.)

Is the function inside a factory instantiated every time?

Take this factory function:
function factory(){
return factory_level2(){
return function complexCode{ // <= Code of interest
//...
}
}
}
const lvl2 = factory()
lvl2();
Does the manufactured function complexCode get instantiated every time the above code is called? Or is the compiler smart enough to know to optimize it into something like this:
function complexCode{
//...
}
function factory(){
return factory_level2(){
return complexCode // Returns reference rather than instantiates?
}
}
The compiler generally cannot and should not optimize the code into your second example. The reason for this is because the scope of the two code are different - meaning they have different closures.
All modern javascript engine in common use (Spidermonkey, Squirrelfish and V8) will compile the instructions of the functions only once. So if this is what you are asking then yes. They are compiled only once and all calls to them will share the same bytecodes.
However, you used the word "instantiation". In OO languages, a class is normally only compiled once. Just like the description of how functions are compiled in javascript above. However, a class can be instantiated into many objects. All objects belonging to the same class will share the same executable code. However they don't share the memory of the variables they use (properties they have). All variables/properties are unique to each object.
The following is an example of OO in a fictional programming language:
class A {
property i;
property j;
method foo () {
print( i+j );
}
}
variable x = new A();
variable y = new B();
x.i = 1;
x.j = 2;
y.i = 10;
y.j = 20;
x.foo(); // should print 3 instead of 30
// because x and y don't share the
// same memory
print( addressof x.foo == addressof y.foo ); // should print true
// because both "foo"
// are actually the same
Javascript functions make the same optimization. In your example factory and factory_level2 and complexCode will be compiled only once. Every call to them will execute code from the same memory address. However, each call will instantiate its own scope - the instance of the scope is the closure.
In most programming languages the behavior of function calls work the same but normally you don't need the concept of closures in some languages because they cannot return functions. Due to the fact that javascript can return a function the scope is instantiated and saved for future use - this long-term instantiation of scope is called a closure. In languages that cannot return functions the temporary activation of scope is called an activation record or also commonly known as the stack frame. The difference between a closure an a stack frame is that the stack frame is deleted at the end of the function call. In languages like javascript the runtime needs to check if the variable in the stack frame is linked to a returned function. If it is then it cannot be deleted because that function may be called in the future. It is thus saved as a closure.
The following is an example in another fictional language:
function A () {
variable i = 0;
return function () {
i++;
print(i);
}
}
variable x = A();
variable y = A();
print( addressof x == addressof y ); // should print true
x(); // prints 1
x(); // prints 2
y(); // prints 1 because even though x and y share the same
// function they don't share the variable i which is
// captured in a closure
Note that all the examples above are in a made up language to illustrate what I'm describing because certain things are difficult or impossible to demonstrate in javascript (such as getting the memory address of a function). However the concepts are true for most modern implementations of javascript (or indeed any implementation of javascript that has had enough pressure to be optimized)
This is technically implementation-dependent. But any decent implementation will only compile the function once and reuse that.
If complexCode() is a closure (i.e. it references variables that are declared in factory() or factory_level2(), all the closure instances will reference the same code object, with different environment objects that contain the variable bindings for that instance.
This is similar to the way class methods are assigned once to the prototype object and reused by all the instances.

When to use an anonymous function in Nodejs?

Recently I was debugging a bit of code that one of my coworkers wrote and found something along the lines of this within a conditional, inside of a larger function.
(function(foo){
...
console.log(foo);
...
})();
So it looks like this very boiled down
function display(db, user, foo) {
if (isValid(db, user) {
(function(foo){
console.log(foo);
})();
}
...
}
Originally it didn't have (); at the end so to my understanding it wasn't even being called but to my broader question, what's the difference between that and something like below? I've seen this syntax a few times but I don't understand how above would be useful for this purpose. My understanding would reason that this just adds unnecessary complexity. Someone please enlighten me!
function display(db, user, foo) {
if (isValid(db, user) {
// without abstract function
console.log(foo);
}
...
}
Thanks :-)
With such a simple example, there is no reason to use an anonymous function like this in node.js or any other JavaScript environment when the inner function could be called directly instead.
When conducting reviews, I often will assume that any console.log (or choose-your-language logging) is accidental. If the surrounding source doesn't do anything of value itself, it is likely only intended to support a (possibly-out-of-date) console.log during development and debugging.
Because JavaScript is single-threaded, constructing an anonymous function of this sort is strictly for scoping. In the case of the original source that didn't have the execution (i.e. it was missing the ()), this is actually a way to "hide" debug code from the runtime while leaving it in-place if a step-through debug ever needed it.
When debugging, it's as easy as adding the ('isValid succeeded') to have it execute all the source inside.
(function(foo){
console.log(foo);
})( /* You're missing a parameter value here; will print 'undefined'. */ );
Sometimes you use an anonymous function to limit the scope of your code. It may come handy if you do not want to pollute the global scope with your variables. Also, it makes dependency injection for testing easier.
Consider the following examples:
var a = 2, b = 3;
function print(x)
{
console.log('x= ', x);
}
print(a+b);
In the above example, the a, b, and print now belongs to the window object. When your code grows it becomes difficult to keep track and avoid of name collisions. The problem becomes even more severe if you are using 3rd party libs etc.
In the example below, your code is wrapped in an anonymous function protecting the global scope. You can also pass parameters to the anonymous function
(function(localParam){
var a = 2, b = 3;
function print(x)
{
console.log('x= ', x);
}
print(a+b);
//also
console.log(localParam); // = safe way to access and global variables
})(globalParam);

Closure memory leak of unused variables

I'd like to understand under which circumstances variables which are no further used are stored in closures and lead to memory leaks. My most preferred outcome would be "there are none", but this doesn't seem to be the case.
From what I understand, once a function is declared inside another function, its internal [[scope]] is assigned the LexicalEnvironment of its encapsulating function. This LexicalEnvironment has reference local variables and the entire scope chain at that point. This basically includes all free variables the function could access (from what I understood of lostechies, javascript closures explained).
Here the first issue arises: this should mean all those variables can be reached as long as the function lives. E.g. the following should already leak:
function a() {
let big = new Array(1000000).join('*'); //never accessed
//function unused() { big; }
return () => void 0;
}
let fstore = [];
function doesThisLeak() {
for(let i = 0; i < 100; i++) fstore.push(a());
}
doesThisLeak();
This luckily doesn't seem to be the case on my firefox. I've received several explanations to why this doesn't leak, from "the jitter is smart" to "LexicalEnvironment is a record type which means GC can collect the unused variables". I still don't know whether either is correct, whether this doesn't leak on all modern runtimes and why.
After further research, I found auth0, four types of leaks in javascript (sadly, there appears to be no html id to jump to, the relevant part is "4: Closures") which shows a way to trick whatever smart thing is collecting the unused variables. In above snippet, when just uncommenting the "unused" function, I do not see RAM usage ever going down again (it was already noted that it could be GC simply did not run for other reasons. However, so far, I am assuming it leaks. I also got told this was limited to firefox, but it appeared to produce similar behavior in chrome)
This example (in case it really does what i believe it does), shows that completely unused variables can leak due to a function declaration in the same scope.
To conclude my problems:
What is the reason for, in the above snippet, "big" getting collected (when "unused" is commented) and does this happen on all modern runtimes?
Assuming the example with the "unused" function not commented leaks, what are best practices to avoid such accidental leaks? Are there any more? I already got the suggestion of null'ing all local variables which are not further used at the end of functions, however, this seems absurdly ugly. I fear using temporary variables for pre-calculations and accidentally leaking.
PS: It is quite hard to make certain that this question has not already been asked in the jungle of questions about memory leaks with closures.
The compiler can examine the code of the returned function to see which free variables it references, and only those variables need to be saved in the closure, not the entire LexicalEnvironment. You can see this by examining the closure in the Javascript debugger.
function a() {
let big = new Array(1000000).join('*');
let small = "abc"; // is accessed
return (x) => small + x;
}
fun = a();
console.dir(fun);
function b() {
let big = "pretend this is a really long string";
function unused() { big; }
return () => void 0;
}
fun = b();
console.dir(fun);
When you expand the first function in the debugger, you'll see small in the Closure property, but not big. Unfortunately, the Chrome compiler doesn't seem to be clever enough to detect when the variable is referenced in an unused function that isn't returned, so it doesn't need to be saved, so we get a leak in b().
Any data that isn't saved in the closure becomes garbage and can be collected, so it won't leak.
After you call a() your fstore has reference to created function () => void only. After a() returns, its scope vars will be deleted. It means that no vars has reference to your new Array(1000000).join('*') and it will be garbage collected. It will be collected the same way if you uncomment unused function because it will deleted too. There are no leaks in your code.
pic1
You can think about Javascript scope chain with the problem.Identify a Function will create a new scope chain.If function's local scope do not have a local variable, it will reference to outside scope of lexical environment, it will keep over in the memory
here's a link

Javascript: why the access to closure variable might be slow

Recently I've read this performance guide Let's make the web faster and was puzzled by "Avoiding pitfalls with closures" recommendations (as if these advices were given for CommonLisp users where variable scoping is dynamic):
var a = 'a';
function createFunctionWithClosure() {
var b = 'b';
return function () {
var c = 'c';
a;
b;
c;
};
}
var f = createFunctionWithClosure();
f();
when f is invoked, referencing a is slower than referencing b, which is slower than referencing c.
It's quite evident that referencing local variable c is faster than b, but if the iterpreter is written properly (without dynamic scoping - something like chained hashtable lookup..) the speed difference should be only marginal. Or not?
You're right. Modern JS engines will optimize the scope chain lookup and the prototype chain lookup like a lot. Means, AFAIK the engine trys to hold some sort of hash-table with access nodes underneath.
This only works if there is no eval() (explicity or implicitly, e.g. setTimeout) or a try-catch clause or a with statement invoked. Because of such constructs, the interpretator can't be sure about how to access data and it needs to "fallback" into a classical scope chain lookup which really means, it has to crawl through all parent context variable / activation objects and try to resolve the searched variable name.
This process of, of course, will take more time for objects/names which are located "far away" from where the lookup processed was started. That in turn means, that accessing data on the global object will always be the slowest.
In your snippet, the lookup process for a would go like
anonymous function -> Execution Context -> Activation Object (not found)
anonymous function -> Execution Context -> [[ Scope ]]
- createFunctionWithClosure
- global scope
createFunctionWithClosure -> Activation Object (not found)
global scope -> Variable Object (found)
The described lookup procedure is for ECMAscript Edition 262 3rd edition. ECMAscript edition 5 has some fundamental changes there.

Categories

Resources