What is lexical scope?
I understand them through examples. :)
First, lexical scope (also called static scope), in C-like syntax:
void fun()
{
int x = 5;
void fun2()
{
printf("%d", x);
}
}
Every inner level can access its outer levels.
There is another way, called dynamic scope used by the first implementation of Lisp, again in a C-like syntax:
void fun()
{
printf("%d", x);
}
void dummy1()
{
int x = 5;
fun();
}
void dummy2()
{
int x = 10;
fun();
}
Here fun
can either access x
in dummy1
or dummy2
, or any x
in any function that call fun
with x
declared in it.
dummy1();
will print 5,
dummy2();
will print 10.
The first one is called static because it can be deduced at compile-time, and the second is called dynamic because the outer scope is dynamic and depends on the chain call of the functions.
I find static scoping easier for the eye. Most languages went this way eventually, even Lisp (can do both, right?). Dynamic scoping is like passing references of all variables to the called function.
As an example of why the compiler can not deduce the outer dynamic scope of a function, consider our last example. If we write something like this:
if(/* some condition */)
dummy1();
else
dummy2();
The call chain depends on a run time condition. If it is true, then the call chain looks like:
dummy1 --> fun()
If the condition is false:
dummy2 --> fun()
The outer scope of fun
in both cases is the caller plus the caller of the caller and so on.
Just to mention that the C language does not allow nested functions nor dynamic scoping.
Lexical Scope in JavaScript
Your understanding of how scope works for standard functions (including closures inside closures) is correct, but for arrow functions this statement is wrong:
"this" is bound to obj because of the lexical scoping of "this" with arrow functions.
With an arrow function this
within the function is the same as whatever this
was outside the function when it was created. It is not bound to obj
in your example, but instead to whatever it was already bound to where that obj
is being created.
It is useful in a situation such as:
this.values.filter( x => x < this.max );
Inside that arrow function this
is the same as it was outside the function. With a regular function it might have been written like this:
this.values.filter( function ( x ) { return x < this.max }.bind( this ) );
or:
var self = this;
this.values.filter( function ( x ) { return x < self.max } );
Lexical scoping in ES6 / Node
As mentioned by Benjamin Gruenbaum, let
and const
don't hoist at all.
As a matter of fact, there are new rules that apply to let
and const
, such as the…
temporal dead zone
Now, if these were var
declarations, everything would be clear. But with let
and const
, ES6 introduces a new concept of the temporal dead zone. This includes a new, subtle dynamic.
Let's have a look at two examples:
Hoisting classically would work in an example like this:
'use strict';
var x = 10;
console.log(x);
console.log(y); // This should NOT crash
var y = 5;
But if we were to replace the var
declarations with let
declarations, it would crash:
'use strict';
let x = 10;
console.log(x);
console.log(y); // This crashes: ReferenceError: can't access lexical declaration `y' before initialization
let y = 5;
Why does this crash?
Because unlike var
assignments, accessing variables defined using let
before the actual let
statement is invalid (they are in the temporal dead zone).
2. Temporal Dead Zone in this case
In this case however, the temporal dead zone is not an issue. Why?
Because while we define the function with the console.log(y)
statement beforehand, the actual function call and thus variable access only happens towards the end of the code. So the variable bindings are only evaluated at this point (thanks again, @BG):
'use strict';
let x = 10;
function f() {
console.log(x);
console.log(y); // This should not yet crash
}
let y = 5;
f(); // console.log(y) is only called here
If you were to reverse the order of let y = 5;
and f();
, your code would crash.
What is lexical scope in reactjs
React is a JavaScript library. The example you've mentioned is of lexical scope. It follows all principles of JavaScript. You can get more on scoping in the below links:
- https://spin.atomicobject.com/2020/04/08/react-contexts-dynamic-scope/
- https://medium.com/the-andela-way/fundamental-javascript-concepts-to-help-you-get-started-with-react-7067763d3697
Related Topics
What Does the Construct X = X || Y Mean
How to Add a Key/Value Pair to a JavaScript Object
What Do Multiple Arrow Functions Mean in JavaScript
What Is Destructuring Assignment and Its Uses
Format JavaScript Date as Yyyy-Mm-Dd
Large Numbers Erroneously Rounded in JavaScript
Chrome/Firefox Console.Log Always Appends a Line Saying 'Undefined'
Explain the Encapsulated Anonymous Function Syntax
Combination of Async Function + Await + Settimeout
Jquery .Live() VS .On() Method For Adding a Click Event After Loading Dynamic Html
Set a Default Parameter Value For a JavaScript Function
How to Work Around JavaScript'S Parseint Octal Behavior
Simplest Code For Array Intersection in JavaScript
In JavaScript, Does It Make a Difference If I Call a Function With Parentheses