在TypeScript(以及JavaScript)中,作用域(Scope)指的是代码中变量、函数、对象等标识符的可见性和生命周期。TypeScript的作用域分为以下几种类型:

1. 全局作用域(Global Scope)

全局作用域中的变量在整个程序中都可以访问。任何在文件最外层定义的变量都在全局作用域中。

示例

  1. var globalVar = "I am global";
  2. function globalFunction() {
  3. console.log(globalVar); // 可以访问globalVar
  4. }
  5. globalFunction(); // 输出: I am global
  6. console.log(globalVar); // 输出: I am global

2. 函数作用域(Function Scope)

函数作用域中的变量只能在该函数内访问。在函数外部不能访问这些变量。

示例

  1. function functionScopeExample() {
  2. var localVar = "I am local";
  3. console.log(localVar); // 输出: I am local
  4. }
  5. functionScopeExample();
  6. console.log(localVar); // 错误: 找不到名称 'localVar'

3. 块作用域(Block Scope)

块作用域是由{}包围的代码块内的作用域。letconst声明的变量具有块作用域。

示例

  1. if (true) {
  2. let blockVar = "I am block-scoped";
  3. console.log(blockVar); // 输出: I am block-scoped
  4. }
  5. console.log(blockVar); // 错误: 找不到名称 'blockVar'

4. 模块作用域(Module Scope)

当使用TypeScript模块(文件)时,每个文件都被视为一个模块,具有自己的作用域。模块中的变量在该模块外部不可见,除非显式导出。

示例

module1.ts:

  1. export const moduleVar = "I am in a module";

module2.ts:

  1. import { moduleVar } from './module1';
  2. console.log(moduleVar); // 输出: I am in a module

5. 类作用域(Class Scope)

类作用域指的是在类内部定义的属性和方法的可见性。TypeScript中有三种访问修饰符:publicprivateprotected

  • public:默认修饰符,类的属性和方法在任何地方都可以访问。
  • private:只能在类的内部访问。
  • protected:只能在类的内部及其子类中访问。

示例

  1. class Example {
  2. public publicVar = "I am public";
  3. private privateVar = "I am private";
  4. protected protectedVar = "I am protected";
  5. public printVars() {
  6. console.log(this.publicVar);
  7. console.log(this.privateVar);
  8. console.log(this.protectedVar);
  9. }
  10. }
  11. const example = new Example();
  12. example.printVars(); // 输出所有变量
  13. console.log(example.publicVar); // 输出: I am public
  14. console.log(example.privateVar); // 错误: 属性“privateVar”为私有属性,只能在类“Example”中访问
  15. console.log(example.protectedVar); // 错误: 属性“protectedVar”受保护,只能在类“Example”及其子类中访问

作用域规则

  • 变量提升(Hoisting)var声明的变量会被提升到函数作用域或全局作用域的顶部。letconst声明的变量不会提升,它们具有块作用域。

    1. console.log(hoistedVar); // 输出: undefined
    2. var hoistedVar = "I am hoisted";
    3. console.log(nonHoistedVar); // 错误: 不能在未声明的情况下使用“nonHoistedVar”
    4. let nonHoistedVar = "I am not hoisted";
  • 暂时性死区(Temporal Dead Zone, TDZ):在使用letconst声明的变量之前,如果尝试访问它们,会抛出错误。这段时间称为“暂时性死区”。

    1. console.log(tdVar); // 错误: 不能在未声明的情况下使用“tdVar”
    2. let tdVar = "I am in TDZ";

总结

理解TypeScript中的作用域对于编写可维护和无错误的代码至关重要。使用块作用域(letconst)替代函数作用域(var)有助于避免变量提升和作用域污染问题。模块和类作用域可以帮助组织代码,提高代码的可读性和复用性。