Closures
arfat.dev
Scope
The scope is an enclosing context in which a variable is associated with a value and is accessible.
let x = 10;
function foo(arg) {
let x = 20;
if (arg > 100) {
let x = 30;
}
}
foo(400)
Refinement of concepts
Important Note: ✋
The inner scopes (or nested blocks) always have access to their parent's, grandparent's, great-graparent's etc. scope.
That means:
if-block can access
- foo's scope (parent)
- Global scope (grand parent)
foo-block can access
- Global scope (parent)
The name resolution (or search) always begins in the current scope and then climbs to outer scopes in order.
arfat.dev
Example 📖
let myName = 'in outer scope';
function printName() {
console.log(myName);
}
printName(); // in outer scope
myName = 'name changed';
printName(); // name changed
Lexical Scope
In short:
an identifier refers to its nearest lexical environment.
"Lexical" means that the as "nesting of scopes that is visible by looking at the source code"
aka Static Scope
"Lexical" means that a scope ONLY has access to values which are part of it's hierarchy in the source code.
Now, Lexical Scope mean that:
You always start the name resolution search at the point of function definition / declaration. NOT at the point of execution.
Example 📖
function sum(a, b) {
let total = a + b;
return total;
}
function anotherFunction() {
let total = 5230;
let returnedValue = sum(19, 200);
console.log(returnedValue); // 219
}
Note:
sum and anotherFunction both have access to the same global scope.
First-class values
In a programming language, a first-class value is a value which can be
- created
- modified
- assigned to a variable.
- passed as an argument,
- returned from a function
Are numbers first class in JS?
What about strings?
In JS, functions are also
first-class 🔥
Functions within Functions
function printerWith(str) {
return function (newStr) {
return newStr + str;
};
}
setTimeout( function () {
console.log('in a callback function')
}, 1000)
When a function is passed as an argument, it's called as (generally) callback.
Closures
A closure refers to the ability of a function to
- remember its lexical parent scope
- have read/write access to variables defined in the parent environment
function a() {
var x = 5;
return function () {
console.log(x);
};
}
var x = 10;
const b = a();
b();
- The red is global scope
- The green is a's scope
- The blue is anonymous function's scope
Test
for (var i = 0; i < 3; i++) {
setTimeout(function log() {
console.log(i);
}, 1000);
}
Test
function a() {
let fn;
{
var x = 5;
fn = function() {
console.log(x);
}
}
return fn;
}
var x = 10;
const b = a();
b();
Test
var a = 100;
function abc(x) {
var a = 10;
return function (y) {
return a + y;
}
}
a = 50;
var inner = abc(20);
function foo() {
var a = 30;
console.log(inner(5));
}
foo();
Test
var e = 10;
function sum(a) {
return function(b) {
return function(c) {
return function(d) {
return a + b + c + d + e;
}
}
}
}
sum(1)(2)(3)
Test
That is, all inner functions share the same parent environment.
let firstClosure;
let secondClosure;
function foo() {
let x = 1;
firstClosure = function () { return ++x; };
secondClosure = function () { return --x; };
x = 2;
console.log(firstClosure());
}
foo();
console.log(firstClosure());
console.log(secondClosure());
3
4
3
function printerWith(str) {
return function (newStr) {
return newStr + str;
};
}
const fn1 = printerWith('!');
const fn2 = printerWith('?');
let returnedValue = fn1('arfat');
console.log(returnedValue);
Test
arfat!
Closures
By Arfat Salman
Closures
Just JS Closures with examples
- 935