Skip to content

Commit e818188

Browse files
Added comprehensive documentation on Scope, Lexical Environment, Block Scope, and Shadowing in JavaScript with code examples and explanations of key concepts.
1 parent 7bde9f9 commit e818188

3 files changed

Lines changed: 370 additions & 0 deletions

File tree

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Episode 7 : Scope and Lexical Environment
2+
3+
This is why JS is confusing
4+
5+
### Case-1
6+
7+
```javascript
8+
function a() {
9+
console.log(b); // surprisingly instead of printing undefined it prints 10.
10+
//So somehow this b could access the b outside the function.
11+
}
12+
13+
var b = 10;
14+
15+
a(); // Function Invocation
16+
```
17+
18+
### Another case: Case-2
19+
20+
```javascript
21+
function a() {
22+
c(); // Function Invocation
23+
24+
function c() {
25+
console.log(b); // when cursor comes here, it still prints out 10 somehow!!
26+
}
27+
}
28+
29+
var b = 10;
30+
31+
a(); // Function Invocation
32+
```
33+
34+
### Another one (DJ KHALED!): Case-3
35+
36+
```javascript
37+
function a() {
38+
var b = 10;
39+
40+
c(); // Function Invocation
41+
42+
function c() {
43+
console.log(b); //it prints the right value. How?
44+
}
45+
}
46+
47+
a(); // Function Invocation
48+
49+
console.log(b); // now when cursor comes here, it prints NOT DEFINED!
50+
```
51+
52+
- This is the intuition behind **scope.**
53+
- Scope in a simple language means where we can access a specific varible or function inside the code.
54+
- Scope in JavaScript is directly related to and dependent on the lexical environment.
55+
- **Lexical Environment** : `local memory + lexical environment of its parent`
56+
- Whenever an EC is created, a Lexical environment(LE) is also created and is referenced in the local EC(in memory space)
57+
- Lexical means hierarchy. In the DJ KHALED (xD) code, function `c` is lexically inside function `a`.
58+
- So in EC of `c()`, variables and function in c (none) + reference of lexical environment of parent `a()` is there
59+
- LE of `a()` in turn is its memory space + reference to LE of parent (Global EC)
60+
- LE of Global EC points to _null_
61+
62+
### Summarize the above points:
63+
64+
call_stack = [GEC, a(), c()]
65+
66+
Now lets also assign the memory sections of each execution context in call_stack.
67+
68+
`c()` = [[lexical environment pointer pointing to a()]]
69+
70+
`a()` = [b:10, c:{}, [lexical environment pointer pointing to GEC]]
71+
72+
GEC = [a:{},[lexical_environment pointer pointing to null]]
73+
74+
### For case -3
75+
76+
- First JS engine searches for b in local memory of c(). Nothing is there.
77+
- So it goes to the reference of Lexical environment of parent `a()`. Here b = 10 is here. So it takes this value, goes back to c() and console prints it.
78+
- Had b not been in `a()`, then pointer would have gone to `a()`'s parent (Global EC and searched there). Had b not been there too, then it goes to LE of global's parent which is null. Now JS engine stops and says b is NOT DEFINED.
79+
- **Lexical environment of c = Local memory of c + LE of A + LE of Global**
80+
- This process of going one by one to parent and checking is called **scope chain**
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# Episode 8 : let, const, temporal dead zone, types of errors
2+
3+
> let and const declarations are hoisted. But it's different from var since they are in temporal deadzone for a time being.
4+
5+
```javascript
6+
console.log(a); // ReferenceError: Cannot access 'a' before initialization
7+
8+
console.log(b); // prints undefined as expected
9+
10+
let a = 10;
11+
12+
console.log(a); // 10
13+
14+
var b = 15;
15+
```
16+
17+
It looks like let isn't hoisted, **but it is**
18+
19+
- Both a and b are actually initialized as _undefined_ in hoisting stage. But var b is inside the storage space of GLOBAL, and a is in a separate memory(script), where it can be accessed only after assigning some value to it first.
20+
- i.e. one can access 'a' only if it is assigned. Thus, it throws error.
21+
- **Temporal Dead Zone** : Time since when the let variable was hoisted until it is initialized some value.
22+
- So any line till before "let a = 10" is the TDZ for a
23+
- Since a is not accessible on global, its not accessible in _window/this_ also
24+
> window.b or this.b -> 15; But window.a or this.a ->undefined, just like window.x->undefined (x isn't declared anywhere)
25+
26+
```javascript
27+
let a = 10;
28+
29+
let a = 100; //this code is rejected upfront as SyntaxError. (duplicate declaration)
30+
31+
-----------------------------------------
32+
33+
let a = 10;
34+
35+
var a = 100; // this code also rejected upfront as SyntaxError. (can't use same name in same scope)
36+
```
37+
38+
Let is a stricter version of var. Now, **const** is even more stricter than let.
39+
40+
- const holds all above properties of let.
41+
42+
```javascript
43+
let a;
44+
45+
a = 10;
46+
47+
console.log(a) // prints 10 properly. Note declaration and assigning of a is in different lines.
48+
49+
50+
-----------------------------------------
51+
52+
53+
const b;
54+
55+
b = 10;
56+
57+
console.log(b); // SyntaxError: Missing initializer in const declaration. (This type of declaration won't work with const. const b = 10 only will work)
58+
59+
60+
-----------------------------------------
61+
62+
const b = 100;
63+
b = 1000;
64+
//this gives us TypeError: Assignment to constant variable.
65+
66+
```
67+
68+
- Till now 3 types of errors have been covered: Syntax, Reference, and Type.
69+
70+
* Uncaught ReferenceError: x is not defined at ...
71+
72+
- This Error signifies that x has never been in the scope of the program. This literally means that x was never defined/declared and is being tried to be accesed.
73+
74+
* Uncaught ReferenceError: cannot access 'a' before initialization
75+
76+
- This Error signifies that 'a' cannot be accessed because it is declared as 'let' and since it is not assigned a value, it is its Temporal Dead Zone. Thus, this error occurs.
77+
78+
* Uncaught SyntaxError: Identifier 'a' has already been declared
79+
80+
- This Error signifies that we are redeclaring a variable that is 'let' declared. No execution will take place.
81+
82+
```javascript
83+
//code example 1.1
84+
let a = 10;
85+
let a = 100;
86+
```
87+
88+
```javascript
89+
//code example 1.2
90+
let a = 10;
91+
var a = 100;
92+
```
93+
94+
Will throw this Syntax error and no code will be run and be rejected affront.
95+
'let' is a strict form of declaration and thus can be done only once.
96+
97+
- Uncaught SyntaxError: Missing initializer in const declaration
98+
99+
- This Error signifies that we haven't initialized or assigned value to a const declaration.
100+
101+
- Uncaught TypeError: Assignment to constant variable
102+
- This Error signifies that we are reassigning to a const variable.
103+
104+
### Type Error:
105+
106+
The Errors that occur due to conflicts with the declaration type. For example re-assigning const type declaration will throw this.
107+
108+
### Syntax Error:
109+
110+
The Errors that occur due to wrong syntax that doesn't match with JS Engine syntactical rules.
111+
112+
For example, if const is not initialized, it will throw syntax error as by syntax, it must initialize if it sees a const declaration.
113+
114+
Also, if variable that is assigned with 'let' declaration is tried to re-declared, then it throws Syntax Error.
115+
116+
### Reference Error
117+
118+
The Errors that occurs if no reference is available for access. Can occur when the variable is no where in scope or maybe it is in temporal dead zone.
119+
120+
### SOME GOOD PRACTICES:
121+
122+
- Try using const wherever possible.
123+
- If not, use let.
124+
- Avoid var.
125+
- Declare and initialize all variables with let to the top to avoid errors to shrink temporal dead zone window to zero.
126+
127+
**NOTE**: If in any interview when asked "Are let and const hoisted?" explain fully about temporal deadzone and all the above concepts too

12_Block_Scope_And_Shadowing.md

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
# Episode 9 : Block Scope and Shadowing
2+
3+
### What is a block?
4+
5+
- Block also known as a _compound statement_ is used to group JS statements together into 1 group. We group them within curly braces {...}
6+
- The purpose is to group multiple statments at a place where JS expects only 1 statement.
7+
8+
```javascript
9+
//code example 1
10+
11+
if(true) some statement
12+
```
13+
14+
But if we want to write more statements to execute after if condition; then:
15+
16+
```javascript
17+
//code example 2
18+
19+
if(true) {
20+
statement 1
21+
statement 2
22+
...
23+
}
24+
```
25+
26+
- The {} block treats all the statements as one statement.
27+
- The if doesnt have any curly braces in syntax.
28+
29+
### **BLOCK SCOPE**
30+
31+
- What are the variables and functions that can be accessed inside the block.
32+
33+
```javascript
34+
//code example 3
35+
36+
{
37+
var a = 10;
38+
let b = 20;
39+
const c = 30;
40+
}
41+
42+
console.log(a);
43+
console.log(b);
44+
```
45+
46+
Outputs:
47+
48+
10
49+
50+
Uncaught ReferenceError: b is not defined
51+
52+
- Behind the Scenes:
53+
54+
- In the BLOCK SCOPE; we get b and c inside it initialized as _undefined_ as a part of hoisting (in a seperate memory space called block)
55+
- While, a is stored inside a GLOBAL scope.
56+
57+
- Thus we say, _let_ and _const_ are BLOCK SCOPED. They are stored in a separate mem space which is reserved for this block. Also, they can't be accessed outside this block.
58+
But var a can be accessed anywhere as it is in global scope.
59+
- Thus, we can't access them outside the Block.
60+
61+
### **What is SHADOWING in JS?**
62+
63+
```javascript
64+
//code example 4
65+
66+
var a = 100;
67+
68+
{
69+
var a = 10; //same name as global var
70+
let b = 20;
71+
const c = 30;
72+
73+
console.log(a); // 10
74+
console.log(b); // 20
75+
console.log(c); // 30
76+
}
77+
78+
console.log(a); // 10 instead of the 100 we were expecting. So block "a" modified val of global "a" as well.
79+
// In console, only b and c are in block space. a initially is in global space(a = 100), and when a = 10 line is run, a is not created in block space, but replaces 100 with 10 in global space itself.
80+
```
81+
82+
- If one has same named variable outside the block, the variable inside the block _shadows_ the outside variable.
83+
- So, a is reassigned to 10. Since both refers to same memory space i.e GLOBAL SPACE. **This happens only for var**
84+
85+
### Instead of var, now let's use let
86+
87+
```javascript
88+
//code example 5
89+
90+
let b = 100;
91+
{
92+
var a = 10;
93+
let b = 20;
94+
const c = 30;
95+
96+
console.log(b);
97+
}
98+
99+
console.log(b);
100+
```
101+
102+
Outputs:
103+
104+
> 20
105+
106+
> 100 // this was what we were expecting in this first place. Both b's are in separate spaces (one in Block(20) and one in Script(another arbitrary mem space)(100))
107+
108+
- In the Scope, we have b in two places. The b outside of the block is in _Script_ SCOPE (seperate memory space for let and const)
109+
- The b inside the block is in _Block_ scope.
110+
- Thus, when in Block scope, 20 is printed and 100 when outside.
111+
- This concept is called "Shadowing".
112+
- It is also true for _const_ declarations.
113+
114+
### Same logic is true even for functions also
115+
116+
```javascript
117+
const c = 100;
118+
119+
function x() {
120+
const c = 10;
121+
console.log(c);
122+
}
123+
124+
x();
125+
126+
console.log(c);
127+
```
128+
129+
Output:
130+
131+
> 10
132+
133+
> 100
134+
135+
### **What is Illegal Shadowing?**
136+
137+
```javascript
138+
// code example 6
139+
140+
let a = 20;
141+
{
142+
var a = 20;
143+
}
144+
```
145+
146+
Outputs:
147+
148+
> Uncaught SyntaxError: Identifier 'a' has already been declared
149+
150+
- We cannot shadow let with var. But it is valid to shadow a let using a let.
151+
- However, we can shadow var with let.
152+
- All scope rules that work in function are same in arrow functions too.
153+
- Since var is function scoped, it is not a problem with the code below.
154+
155+
```javascript
156+
// code example 7
157+
158+
let a = 20;
159+
160+
function x() {
161+
var a = 20;
162+
}
163+
```

0 commit comments

Comments
 (0)