How clearInterval() clears a timerID inside of a setInterval()? - javascript

I am new to Javascript and have came across to the topic of stack. In the following piece of code (which is simple in order to focus on basics instead of syntax), I can clear timerID inside of my function expression variable. It is quite common to do so, but my question is how the stack is made here? To be more clear, how the order of things goes on to clear the variable in which the clearer itself lives? And how the "console.log('DONE!')" is called after clearInterval()?
function countNumbers(number){
var timer = setInterval(function(){
number++;
if(number >= 10){
clearInterval(timer);
console.log('DONE!');
}
else {
console.log(number);
}
},1000)
}

When a inner function is maintaining a reference to a variable of an outer function in JavaScript a clousure is formed, that is the members of the outer function is not destroyed when the outer function is done running since it's variables are still being referred from another function.
This is because when a function is executed a new Execution Context is created for that function's environment. It maintains a scope chain and is then pushed to the execution stack in the order of execution.
There is a global Execution context, then the invocation of the countNumbers creates its own execution context and finally the execution context of the callback is created. The callback function execution context maintains a pointer to the scope of the countNumbers function's execution context which maintains a pointer to the execution context of the global:
In your case, when the setInterval() runs it immediately/synchronously returns the ID and it is set in the timer variable. Since the timer variable is defined in the scope of the countNumbers function the inner/callback function forms a clousure over it. The execution context of the callback can reach and access the timer variable through the scope chain.
Now when you run the setInterval the callback is queued and executed at the specified interval asynchronously. Due to the clousure formed earlier the callback has access to the timer variable declared in the outer function scope, so when the number reaches 10 it can use that value of the ID from the outer function scope to cancel the interval.

Related

lexical this and closures

I'm trying to understand how the arrow function passed to setTimeout, remembers the value of this from the previous execution context. I know that the this value is looked up using lexical scoping rules when executing arrow functions. Does that mean the arrow function closes over variables and the this keyword?
var obj = {
name: 'TestName',
func: function() {
console.log(this)
setTimeout(() => console.log(this), 1000)
}
}
obj.func() //{name: "TestName", func: ƒ}
Actually the whole point of using the fat arrow notation is to inherit the parent scope. Main application of arrow functions is to pull down the parent scope.
When we invoke a setTimeout the chain happens as follows-:
Call goes into Call-Stack.
It is transferred to Web-Browser api space, which waits till the interval time.
Now after interval time is completed it'll be handled by Event-Loop which will transfer it to JS-queue.
The command execution will wait till other items in queue finish executing and then it'll transfer the execution flow again to Call-Stack whenever it is empty.
Now the command inside setTimeout will be executed.
JS execution flow
Does that mean the arrow function closes over the this keyword?
Yes, that's exactly what happens.

Closure of function defined as an argument

Disclaimer: This question is purely curiosity driven and has to do a lot with how the javascript works.
I understand why the following code works. Due to closures, foo has access to the scope where a resides. This makes sense.
var a = 10
var foo = function(){
console.log(a);
}
setTimeout(foo,1000)
However, i wonder why the following also works (explained right after).
var a = 10
setTimeout(function(){
console.log(a);
},1000)
The function is defined in the argument of the function receiving it and essentially was never a closure to the scope that contains a. We know that when a function receives an argument, it creates a local variable for that argument so for example
var outerVar="5"
var bar = function(a){
//implicitly, var a = outerVar happens here
console.log(a)
}
bar(something);
So following that logic, the function passed to setTimeout couldnt have access to a and yet it does.
Im suspecting that when a function is defined in the argument space what happens is, it realy is defined before being assigned as an argument but have no proof of that. Any pointers highly appreciated.
Thanks a bunch.
It's not exactly closure, but it's close.
Strictly speaking, closure is when a variable's scope ends, but is still enclosed in an inner function that still lives on:
function createTimer() {
let counter = 0;
return function() {
return counter++;
}
}
const timer = createTimer(); // function() { ... }
console.log(timer(), timer(), timer()); // 0, 1, 2
The function in which counter is defined has returned, the scope ended, and under normal circumstances, counter should have died and garbage collected. But the inner function returned from createTimer() still has a reference to it, from the enclosed scope, that is a closure.
In JavaScript, every function has access to all of the scopes of all of its ancestors, this is what you're seeing here.
The function passed to setTimeout() has access to a because a is defined in the scope around it.
When you look at a javascript code and see how it works, the best way according to me is first understand the javascript engine how it works.
First it traverses the code and assigns all the variables to the scope and further more in the second trace it assigns the values based on the scopes.
So in your first code,
The engine first traverses and assigns
var a to global scope,
var foo as global scope,
Then when setTimeout runs it calls foo function and logs the value of a as that of the global a as it doesnt have any local “a” so checks the lexical scoping.
In your second code,
Var a is again global scoped
and no other declaration this time.
In second traverse it assigns the value 10 to a and interprets the settimeout and prints the value
In your third code,
Same as the second one except the fact that instead what “foo” was giving to the settimeout function, you wrote your callback function then n there itself.
By the time l it executed the setTimeout,
Each of your codes have the value for “a” in the global scope that they are accessing.

What is the 'Execution Context' in JavaScript exactly?

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.

JavaScript Lexical Scoping and Life of Variable

I was curious why this works:
function doThis(){
counter = 0;
return counter;
};
console.log(counter); // returns "reference error: can't find variable"
which makes sense, as the variable does not exist outside of the function. But if I make a function that self executes:
(function doThis(){
counter = 0;
return counter;
})();
console.log(counter); // returns 0
How come the variable counter still exists? It's not a closure, there's nothing that seems to be referencing this variable from the outside, so shouldn't it be destroyed by garbage collection?
You are creating it as a global as you haven't included var before the variable name.
The function in the first example hasn't been invoked so the variable has not been created yet, in the second one it has so that is why you get 0
What your code should be doing is:
function doThis(){
var counter = 0;
return counter;
};
First edit them so that it is instantly clear what's happening (no leaving out var hacks):
function doThis(){
window.counter = 0;
return counter;
};
console.log(window.counter); // returns undefind
And:
(function doThis(){
window.counter = 0;
return counter;
})();
console.log(window.counter); // returns 0
Can you now see what's happening? The function defines a global variable so of course it's not available until the function is called. window refers to the [object global] in browsers.
This is the reason you always want to use either global.something OR var something, so that it's very clear to anyone whether you intend to use global or local variable. If you used var in the OP, the variable would be local.
Since you are not declaring it with "var" it gets assigned to the global scope which is visible out side of the function. In the first example you are not executing the function so the counter is never defined where as in the second example you invoke the function and counter gets assigned to the global scope
In the first example you haven't called the function and so counter doesn't exist yet (because the code inside the function hasn't executed yet). In the second example, you have defined a function literal and you are self-invoking it. The code inside the function execute and counter is now defined.
Furthermore counter is a global variable because you haven't defined it using var and so it is visible to the scope outside the function. It's the same as doing window.counter = 0.
Now if you had done the following:
(function doThis(){
var counter = 0; //notice the var
return counter;
})();
counter would still be undefined because it is local to the scope of the function.
So to recap:
In the first example counter is undefined because the code hasn't run yet. If you actually call the function, you will get the same behavior as the second example.
In the second example counter is defined and is a global variable (basically the same as window.counter) and it is defined because the code inside the function was executed when you defined it and self-invoked it.
In the third example counter is unknown to the global scope because it is local to the function inside which it was defined (because var was used).
As you know, in JavaScript, if you declare a variable without "var" keyword, it will be added to the global scope(window object).
But if a variable is declared within a function without using "var" keyword, it won't be added to the global scope(window object) until that particular function is invoked.
In JavaScript, you have to understand about execution context creation.
when the complete JS file is interpreted, the the memory is allocated for all the functions and variables(hoisting).
Please note that all the variables which are declared outside of the functions are added to the global scope(window object).
Execution phase:
As JS code execution is synchronous(only one line at a time) and single threaded, an execution stack is created and the "global execution context" is pushed to the execution stack.
If a function invocation is encountered in the execution, "function execution context" is created for the corresponding function and pushed to the same stack.
Now during function execution, JS engine parse the code and if it come across a variable, the memory is allocated and if the variable is declared without "var" keyword, it will add this particular variable to the global scope. otherwise that particular variable will be part of function scope(local scope).
Now let's check your code snippets:
function doThis(){
counter = 0;
return counter;
};
console.log(counter); // returns "reference error: can't find variable"
in this example, as the doThis() function is never executed, variable "counter " is not allocated any memory and not part of any scope(global/local). hence in the console log, you see a reference error.
(function doThis(){
counter = 0;
return counter;
})();
console.log(counter); // returns 0
As its a self invoking function, "counter" variable will be allocated memory and moved to the global scope(window object). hence you can see the value of the "counter" variable in the console log.

Using JavaScript closures in setTimeout

I'm using setTimeout to emulate rendering, and I came to the structure like this:
var Renderer = new Class (
{
Implements: Events,
initialize()
{
this.onRender();
},
onRender: function()
{
// some rendering actions
setTimeout(this.onRender.bind(this), 20);
}
});
Does that code have potential memory leaks because of infinite nesting of closures? Or everything is ok? The only solution I came so far is to rewrite it to usual
function Renderer()
{
var onRender = function()
{
// rendering
setTimeout(onRender, 20);
};
onRender();
};
But I don't want to lose Mootools Events and Classes.
For some reasons I can't use a "singleton" (like window.renderer = new Renderer();) too
Your code is fine, but Andy's answer is misleading because it confuses the scope chain with execution context and, by extension, call stack.
First, setTimeout functions do not execute in the global scope. They still execute in a closure and can access variables from outer scopes. This is because JavaScript uses static scope; that is, the scope chain of a function is defined at the moment that function is created and never changes; the scope chain is a property of the function.
Execution context is different and separate from the scope chain in that it is constructed at the time a function is invoked (whether directly – func(); – or as the result of a browser invocation, such as a timeout expiring). The execution context is composed of the activation object (the function's parameters and local variables), a reference to the scope chain, and the value of this.
The call stack can be thought of as an array of execution contexts. At the bottom of the stack is the global execution context. Each time a function is called, its parameters and this value are stored in a new 'object' on the stack.
If we were to change your onRender function to simply call itself (this.onRender()), the stack would quickly overflow. This is because control would never leave each successive onRender function, allowing its execution context to be popped off the call stack. Instead, we go deeper and deeper with each onRender waiting for the next onRender to return, in an infinite cycle broken only when the stack overflows.
However, with a call to setTimeout, control returns immediately and thus is able to leave the onRender function, causing its execution context to be popped off the stack and discarded (to be freed from memory by the GC).
When the timeout expires, the browser initiates a call to onRender from the global execution context; the call stack is only two deep. There is a new execution context – which by default would inherit the global scope as its this value; that's why you have to bind to your Renderer object – but it still includes the original scope chain that was created when you first defined onRender.
As you can see, you're not creating infinite closures by recursion because closures (scope chains) are created at function definition, not at function invocation. Furthermore, you're not creating infinite execution contexts because they are discarded after onRender returns.
We can make sure you're not leaking memory by testing it. I let it run 500,000 times and didn't observe any leaking memory. Note that the maximum call stack size is around 1,000 (varies by browser), so it's definitely not recursing.

Categories

Resources