likes
comments
collection
share

TypeScript 命名空间

作者站长头像
站长
· 阅读数 13

模块化对编程语言的重要不言而喻。但是早期的 TypeScript 并没有模块化规范。为了实现代码的封装,像 Java,C#等语言一样,TypeScript 采用了命名空间。

命名空间声明

命名空间使用 namespace 关键字表示,然后在后面的大括号中去定义各种值包括变量,函数,类,接口等,比如:

namespace Util {
  const _private = '私有属性'
  
  export const name = 'Util'
  
  export function isString(val: any) {
    return typeof val ==='string'
  }
}

这段代码中定义了一个 Util 命名空间,该命名空间内定义两个变量和一个方法,用来判断数据类型。如果是供外界使用的方法和属性,要使用 export 进行导出,这样外界才能访问到:

console.log(Util.name)
Util.isString('abc')

没有使用 export 导出的变量,函数等,只能在声明空间内部使用。

命名空间支持嵌套使用,比如:

namespace A {
    // 暴露出去的命名空间也要使用 export
    export namespace B {
        export const name = 'name'
    }
}

使用时按照顺序访问即可:

console.log(A.B.name)

和接口一样,同名的命名空间也支持合并:

namespace Util {
  export var version = 10
  export function isString(val: any) {
    return typeof val === 'string'
  }
}

namespace Util {
  export function isObject(val: any) {
    return typeof val =='object' && val!== null;
  }
}

模块之间存在依赖时,可以使用 import 关键字来导入另一个模块。定义在多个文件中的命名空间如果存在依赖时,要使用三斜线指令来管理依赖。

假如有两个文件,b.ts 依赖 a.ts 文件的命名空间声明的一个方法,可以这样做:

// util.ts
namespace Util {
  export var version = 10
  export function isString(val: any) {
    return typeof val === 'string'
  }
}

// index.ts
/// <reference path="util.ts" />

Util.isString('abc')

这样以三条斜线 /// 开头的一句注释,就是三斜线指令,作用类似于导入模块,用来引入当前文件所依赖的另一个文件。

命名空间本质

使用 tsc 命令将上面的 Util 命名空间进行编译,得到的 JS 代码是:

var Util;
(function (Util) {
    Util.version = 10;
    function isString(val) {
        return typeof val === 'string';
    }
    Util.isString = isString;
    function isObject(val) {
        return typeof val == 'object' && val !== null;
    }
    Util.isObject = isObject;
})(Util || (Util = {}));

可以发现,命名空间其实就是一个 IIFE(立即调用函数表达式)。在 ES6 以前,前端也是利用 IIFE 去模拟实现模块化。

小结

命名空间的作用是对代码进行封装和隔离。现在更推荐使用标准的模块化规范,它支持天然的以文件来分割代码,减少了显式的 namespace 声明。