TypeScript 命名空间
模块化对编程语言的重要不言而喻。但是早期的 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 声明。
转载自:https://juejin.cn/post/7222651312073703479