一,前言
在js中,为了避免对全局的污染,可以使用命名空间,
在模块化被广泛使用后,命名空间就很少被使用了
上一篇介绍了TS的模块化,虽然在模块中不再及需要考虑全局污染的问题
但如果使用了全局类库,仍需要使用命名空间
本篇介绍TS的命名空间
二,命名空间的定义
使用namespace关键字声明TS命名空间
在命名空间内可定义任意变量,仅能在命名空间下可见
如果要使命名空间内的变量全局可见,需要使用export关键字导出
namespace.ts
// 命名空间
namespace Shape {
const pi = Math.PI
// 全局可见
export function cricle(r: number){
return pi * r ** 2
}
}
二,命名空间的拆分
随着命名空间的增大,命名空间也是可以进行拆分的
namespace2.ts
namespace2.ts中有一个和namespace.ts同名的命名空间
namespace Shape {
export function square(x: number){
return x * x
}
}
这样,相当于一个命名空间分布在两个ts文件中,共享一个命名空间
三,命名空间的使用
直接使用命名空间名称进行访问即可
namespace2.ts
// 命名空间
namespace Shape {
export function square(x: number){
return x * x
}
}
console.log(Shape.cricle(1)) // namespace1.ts
console.log(Shape.square(1)) // namespace2.ts
注意:
命名空间和模块不要混用,
不要在一个模块中使用命名空间,最好在全局使用]
使用方法:
将命名空间的ts文件,编译成为js文件,在index.html中引入
将ts文件编译成js文件:
tsc ./src/namespace2.ts
报错原因:由于cricle方法在namespace.ts中定义,namespace2.ts中找不到
namespace2.ts引用namespace.ts
使用三斜线指令: /// <reference path="引用文件的相对路径">
/// <reference path="namespace.ts"/>
// 命名空间
namespace Shape {
export function square(x: number){
return x * x
}
}
console.log(Shape.cricle(1)) // namespace1.ts
console.log(Shape.square(1)) // namespace2.ts
重新执行命令,生成namespace.js和namespace2.js文件
namespace.js:
// 命名空间
var Shape;
(function (Shape) {
var pi = Math.PI;
// 全局可见
function cricle(r) {
return pi * Math.pow(r, 2);
}
Shape.cricle = cricle;
})(Shape || (Shape = {}));
namespace2.js:
/// <reference path="namespace.ts"/>
// 命名空间
var Shape;
(function (Shape) {
function square(x) {
return x * x;
}
Shape.square = square;
})(Shape || (Shape = {}));
console.log(Shape.cricle(1)) // namespace1.ts
console.log(Shape.square(1)) // namespace2.ts
命名空间的实现原理:
命名空间被编译成了一个立即执行函数,函数创建了一个闭包
在闭包中的私有成员,就是未导出成员
导出成员会被挂载在一个全局变量下
在src/tpl/index.html中引入js文件:
...
<body>
<div class="app"></div>
<script src="src/namespace.js"></script>
<script src="src/namespace2.js"></script>
</body>
...
输出结果:
3.141592653589793
1
四,命名空间的成员别名
如上,在访问命名空间的成员时,需要加上命名空间的名称,如Shape
为了简便,也可以为命名空间成员设置别名,直接访问
// 为命名空间成员设置别名
import cricle = Shape.cricle
console.log(cricle(1))
五,结尾
命名空间本质上就是一个闭包,用来隔离作用域
TS的命名空间是对全局变量时代的兼容
在一个完全的模块化系统中,可以不必使用命名空间