在代码量较大的情况下,为了避免各种变量命名相冲突,可以将类似功能的函数、类、接口等放置到命名空间中
在TypeScript
中的命名空间中的对象、类、函数等可以通过export
暴露出来通过命名空间名.类名
等来使用
这个暴露是暴露在命名空间外,不是将其在模块中暴露出去
命名空间和模块的区别:
-
命名空间:内部模块,主要用于组织代码,避免命名冲突
-
模块:
TypeScript
的外部模块的简称,侧重代码的复用,一个模块里可能会有多个命名空间namespace Validation { // 通过namespace关键词创建一个命名空间 export interface StringValidator { } const lettersRegexp = /^[A-Za-z]+$/; const numberRegexp = /^[0-9]+$/; export class LettersOnlyValidator implements StringValidator { // 要在外部使用必须导出 isAcceptable(s: string) { // 函数内部可以不导出 return lettersRegexp.test(s); } } export class ZipCodeValidator implements StringValidator { isAcceptable(s: string) { return s.length === 5 && numberRegexp.test(s); } } } // Some samples to try let strings = ["Hello", "98052", "101"]; // 在外界就可以直接通过Validation.StringValidator访问命名空间内部导出的接口 let validators: { [s: string]: Validation.StringValidator; } = {}; // 上面接口的意思是一个对象,对象中的每个成员都是有isAcceptable接口方法的实例化对象 validators["ZIP code"] = new Validation.ZipCodeValidator(); validators["Letters only"] = new Validation.LettersOnlyValidator(); // Show whether each string passed each validator for (let s of strings) { for (let name in validators) { console.log(`"${s}" - ${validators[name].isAcceptable(s) ? "matches" : "does not match"} ${name}`); } }
1. 多文件中的命名空间
1.1 通过export
和impot
进行使用
// module.ts
export namespace A {
interface Animal {
name: string;
eat(): void;
}
export class Dog implements Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
eat(): void {
console.log(this.name + "吃狗粮");
}
}
}
import { A } from "./module";
let dog = new A.Dog("狗"); // 传入命名空间
dog.eat();
1.2 通过三斜线指令引入
三斜线指令:包含单个XML
标签的单行注释,注释的内容会做为编译器指令使用,三斜线引用告诉编译器在编译过程中要引入的额外的文件
三斜线指令仅可放在包含它的文件的最顶端。 一个三斜线指令的前面只能出现单行或多行注释,这包括其它的三斜线指令。 如果它们出现在一个语句或声明之后,那么它们会被当做普通的单行注释,并且不具有特殊的涵义
这里只用///<reference path=""/>
,其余用法在 TypeScript中文文档 查看
/// <reference path="..." />
指令是三斜线指令中最常见的一种,它用于声明文件间的 依赖,三斜线引用告诉编译器在编译过程中要引入的额外的文件,也就是会引入对应path的文件
// Validation.ts
namespace Validation {
export interface StringValidator {
isAcceptable(s: string): boolean;
}
}
// LettersOnlyValidator.ts
/// <reference path="Validation.ts" />
namespace Validation {
const lettersRegexp = /^[A-Za-z]+$/;
export class LettersOnlyValidator implements StringValidator {
isAcceptable(s: string) {
return lettersRegexp.test(s);
}
}
}
// ZipCodeValidator.ts
/// <reference path="Validation.ts" />
namespace Validation {
const numberRegexp = /^[0-9]+$/;
export class ZipCodeValidator implements StringValidator {
isAcceptable(s: string) {
return s.length === 5 && numberRegexp.test(s);
}
}
}
/// <reference path="Validation.ts" />
/// <reference path="LettersOnlyValidator.ts" />
/// <reference path="ZipCodeValidator.ts" />
// Some samples to try
let strings = ["Hello", "98052", "101"];
// Validators to use
let validators: { [s: string]: Validation.StringValidator; } = {};
validators["ZIP code"] = new Validation.ZipCodeValidator();
validators["Letters only"] = new Validation.LettersOnlyValidator();
// Show whether each string passed each validator
for (let s of strings) {
for (let name in validators) {
console.log(`"${s}" - ${validators[name].isAcceptable(s) ? "matches" : "does not match"} ${name}`);
}
}
2. 别名
别名是另一种简化命名空间操作的方法是使用import q = x.y.z
给常用的对象起一个短的名字,不要与用来加载模块的import x = require('name')
语法弄混了,这里的语法是为指定的符号创建一个别名
可以用这种方法为任意标识符创建别名,也包括导入的模块中的对象
namespace Shapes {
export namespace Polygons {
export class Triangle { }
export class Square { }
}
}
import polygons = Shapes.Polygons; // 用 polygons代替Shapes.Polygons,相当于C语言的define
let sq = new polygons.Square(); // Same as "new Shapes.Polygons.Square()"
并没有使用
require
关键字,而是直接使用导入符号的限定名赋值。与使用var
相似,但它还适用于类型和导入的具有命名空间含义的符号。 重要的是。对于值来讲,import
会生成与原始符号不同的引用,所以改变别名的var
值并不会影响原始变量的值
网友评论