Lexical environment
Lexical environment consists of two parts:
- Environment record – an object that stores all local variables as their properties.
- A reference to an external lexical environment, associated with external code.
The global lexical environment is created before script execution and has no outer lexical environment.
// Global lexical environment
let a = 'hello' // => hello
let b // => undefined
b = 'world' // => world
Copy the code
A and B are properties of the object that the environment records, and they are assigned values when they are declared or later.
let who = 'Ming'
function say(content) {
let date = new Date()
alert(`${who}Said:${content} | at ${date}`)
}
say('Hello, world! ')
Copy the code
The say() function can form a lexical environment because the function refers to the external lexical environment (that is, the attribute who of the environment record). When the say() function accesses the external lexical environment, it first searches the internal lexical environment, then the external lexical environment, then the more external lexical environment, and so on until it reaches the global lexical environment.
closure
The combination of a function and its lexical environment is a closure. That is, closures allow you to access the scope of an inner function from within its outer function. Ps: this definition was simplified as the closure – JavaScript | MDN.
First let’s look at a simple counter example:
function count() {
let record = 0
return record++
}
let v = 0
v = count()
v = count()
console.log(v) / / 0
Copy the code
We found that when we executed count() twice, it still returned 0.
In object-oriented programming, objects allow us to associate certain data (attributes of an object) with one or more methods, which maintain an environment that can be continuously manipulated:
let counter = {
_record: 0.set count(record) {
this._record = record
},
get count() {
return this._record++
}
}
let v = 0
v = counter.count
v = counter.count
console.log(v) / / 1
Copy the code
Can a counter case be implemented if a counter operation is performed with a closure?
function count() {
let record = 0
return function f() {
return record++
}
}
let v = count()
console.log(v()) / / 0
console.log(v()) / / 1
Copy the code
The counter case was successfully implemented using closures.
V is a reference to the f() function created when count() is executed. V maintains a lexical environment. Therefore, when count() is called multiple times, the variable record is still available and can be operated continuously.
The f() function and its lexical context are a closure, or looking up, the count() function is a closure, and the inner function f() can access any local variable in the scope of the outer function under the closure.
Finally, the Authoritative Guide to JavaScript states that “all JavaScript functions are closures.”