Could someone please give me a brief introduction to lexical scoping?
相关问题
- Is there a limit to how many levels you can nest i
- How to toggle on Order in ReactJS
- void before promise syntax
- Keeping track of variable instances
- Can php detect if javascript is on or not?
I understand them through examples. :)
First, Lexical Scope (also called Static Scope), in C-like syntax:
Every inner level can access its outer levels.
There is another way, called Dynamic Scope used by first implementation of Lisp, again in C-like Syntax:
Here
fun
can either accessx
indummy1
ordummy2
, or anyx
in any function that callfun
withx
declared in it.will print 5,
will print 10.
The first one is called static because it can be deduced at compile-time, 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.
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:
The call chain depends on a run time condition. If it is true, then the call chain looks like:
If the condition is false:
The outer scope of
fun
in both cases is the caller plus the caller of the caller and so on.Just to mention that C language does not allow nested functions nor dynamic scoping.
Note this is taken from here
A lexical scope in Javascript means that a variable defined outside a function can be accessible inside another function defined after the variable declaration. But the opposite is not true, the variables defined inside a function will not be accessible outside that function.
This concept is heavily used in closures in Javascript.
Let say we have the below code.
Now, when you call add() --> this will print 3.
So, add() function is accessing the global variable x which is defined before method function add. This is called due to lexical scoping in javascript.
Here's a different angle on this question that we can get by taking a step back and looking at the role of scoping in the larger framework of interpretation (running a program). In other words, imagine that you were building an interpreter (or compiler) for a language and were responsible for computing the output, given a program and some input to it.
Interpretation involves keeping track of three things:
1) State - namely, variables and referenced memory locations on the heap and stack.
2) Operations on that state - namely, every line of code in your program
3) The Environment in which a given Operation runs - namely, the projection of State on an Operation.
An interpreter starts at the first line of code in a program, computes its environment, runs the line in that environment and captures its effect on the program's state. It then follows the program's control flow to execute the next line of code, and repeats the process till the program ends.
The way you compute the environment for any operation is through a formal set of rules defined by the programming language. The term "binding" is frequently used to describe the mapping of the overall state of the program to a value in the environment. Note that by "overall state" we do not mean global state, but rather the sum total of every reachable definition, at any point in the execution)
This is the framework in which the scoping problem is defined. Now to the next part of what our options are.
This is the gist of dynamic scoping, wherein the environment that any code runs in is bound to the state of the program as defined by its execution context.
In other words, with Lexical Scope the environment that any code sees is bound to state associated with a scope defined explicitly in the language, such as a block or a function.
Lets try the shortest possible definition:
Lexical Scoping defines how variable names are resolved in nested functions: inner functions contain the scope of parent functions even if the parent function has returned.
That is all there is to it!
There is an important part of the conversation surrounding Lexical and Dynamic Scoping that is missing: a plain explanation of the lifetime of the scoped variable - or when the variable can be accessed.
Dynamic scoping only very loosely corresponds to "global" scoping in the way that we traditionally think about it (the reason I bring up the comparison between the two is that it has already been mentioned - and I don't particularly like the linked article's explanation); it is probably best we don't make the comparison between global and dynamic - though supposedly, according to the linked article, "...[it] is useful as a substitute for globally scoped variables."
So, in plain English, what's the important distinction between the two scoping mechanisms?
Lexical scoping has been defined very well throughout the answers above: lexically scoped variables are available - or, accessible - at the local level of the function in which it was defined.
However - as it is not the focus of the OP - dynamic scoping has not received a great deal of attention and the attention it has received means it probably needs a bit more (that's not a criticism of other answers, but rather a "oh, that answer made we wish there was a bit more"). So, here's a little bit more:
Dynamic scoping means that a variable is accessible to the larger program during the lifetime of the function call - or, while the function is executing. Really, Wikipedia actually does a nice job with the explanation of the difference between the two. So as not to obfuscate it, here is the text that describes dynamic scoping: