在 TypeScript(以及 JavaScript)中,闭包描述了函数能够访问其声明时所在作用域的变量,即使该函数在其声明的作用域之外被调用的现象。
定义:闭包是指一个函数能够记住并访问其词法作用域(lexical scope)中的变量,即使这个函数是在其词法作用域之外执行。
闭包的核心原理
TypeScript 中的闭包示例
闭包的用途
TypeScript 对闭包的增强
function createCounter(initial: number): () => number {let count = initial;return function(): number {return count++;}; }// 类型推断会正确识别返回的函数类型 const counter = createCounter(10); console.log(counter()); // 10 console.log(counter()); // 11
原理深入剖析:执行上下文与词法环境
在底层,JavaScript 引擎通过执行上下文和词法环境来实现闭包。
-
调用
outerFunction(10)
:-
创建一个新的执行上下文,并将其推入调用栈。
-
创建对应的词法环境,其中包含了参数
outerValue
和局部变量outerString
。 -
定义
innerFunction
。此时,innerFunction
的内部属性[[Environment]]
会被设置为当前(即outerFunction
的)词法环境的引用。这一步至关重要,它建立了作用域链的连接。
-
-
outerFunction
执行完毕:-
其执行上下文从调用栈中弹出。
-
但是,因为返回的
innerFunction
的[[Environment]]
仍然引用着outerFunction
的词法环境,所以这个词法环境不会被垃圾回收机制销毁。它被保留在内存中,以便innerFunction
将来使用。
-
-
调用
closure(5)
(也就是innerFunction(5)
):-
为
innerFunction
创建一个新的执行上下文和词法环境。 -
这个新词法环境的外部环境引用指向的就是之前在
[[Environment]]
中保存的那个outerFunction
的词法环境。 -
当
innerFunction
尝试访问outerValue
或outerString
时,引擎会沿着这条作用域链查找,成功在outerFunction
的词法环境中找到它们。
-