Typescript中闭包的原理
在 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
实例
让我们看一个用 TypeScript 编写的经典例子:
function outerFunction(outerValue: number) { // 外部函数的变量 const outerString: string = "Hello"; // 内部函数 -> 闭包开始形成 function innerFunction(innerValue: number): void { console.log(`Outer value: ${outerValue}`); console.log(`Outer string: ${outerString}`); console.log(`Inner value: ${innerValue}`); console.log(`Total: ${outerValue + innerValue}`); } // 返回内部函数,使其能够在 outerFunction 的作用域外被执行 return innerFunction; } // 调用 outerFunction,它返回 innerFunction // 此时,closure 就是一个闭包实例,它“关闭”了 outerFunction 的作用域 const closure = outerFunction(10); // 在 outerFunction 的执行上下文已经销毁后,调用 closure // 但是 closure 仍然能访问到 outerValue 和 outerString closure(5); // 输出: // Outer value: 10 // Outer string: Hello // Inner value: 5 // Total: 15
原理深入剖析:执行上下文与词法环境
在底层,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的词法环境中找到它们。
-

浙公网安备 33010602011771号