作用域链的形成与查找分析
- 形成:当一个函数被定义时,它会创建一个作用域,这个作用域包含了函数内部定义的变量以及它外部(父级)作用域的变量。对于
inner
函数来说,它的作用域链会首先包含自身的局部作用域,然后向上链接到outer
函数的作用域,再往上如果有更外层函数,会继续链接,直到全局作用域。
- 查找:当
inner
函数访问一个变量时,它会首先在自身的局部作用域中查找,如果找不到,就会沿着作用域链向上查找,直到找到该变量或者到达全局作用域(如果还没找到,在非严格模式下会创建一个全局变量,严格模式下会报错)。
闭包的作用
- 保持作用域:闭包使得内部函数(
inner
)能够访问并保持外部函数(outer
)的作用域,即使外部函数已经执行完毕并返回。
- 数据私有性:通过闭包,外部函数的局部变量只能通过内部函数来访问和修改,外部代码无法直接访问这些变量,从而实现数据的私有性。
- 模块封装:可以将相关的变量和函数封装在一个闭包内,通过返回特定的接口函数,实现模块的功能封装,只暴露必要的接口给外部使用。
代码示例及解释
function outer() {
let privateVariable = 10; // outer函数的局部变量,具有私有性
function inner() {
return privateVariable; // inner函数访问outer函数的局部变量
}
return inner;
}
const closure = outer();
console.log(closure()); // 输出: 10
// 这里无法直接访问privateVariable,因为它是outer函数的私有变量
// console.log(privateVariable); // 报错: privateVariable is not defined
- 在上述代码中,
outer
函数返回inner
函数。inner
函数形成了一个闭包,因为它引用了outer
函数的局部变量privateVariable
。
- 当
outer
函数执行完毕并返回inner
函数后,outer
函数的作用域本应销毁,但由于inner
函数形成了闭包,outer
函数的作用域被保留下来。
- 通过
closure = outer()
,closure
实际上是inner
函数,调用closure()
可以访问到privateVariable
的值,而外部代码无法直接访问privateVariable
,实现了数据的私有性和模块封装。