TypeScript中的命名空间—namespace

TypeScript中的命名空间—namespace

什么是命名空间?在很多语言中都有这个概念。

命名空间是为了解决命名冲突。比如你在代码的不同地方,都定义了同名但是不同含义的函数、变量等,虽然不提倡这么做,但是有时候需要这么做。那怎么办呢?可以选择将同名但是不同含义的函数、变量等分别写在不同的命名空间中,就不怕有冲突报错啦!

命名空间的关键字是namespace

namespace tsNamespace {

let ownerName: string = "tsNameSpace";

export function sayHello(name: string) {

console.log(ownerName, "Hello,", name);

}

}

上面就是一个简单的namespace的定义。

要想访问namespace中的变量或者方法,那么就要在方法或者变量的前面加上export,这样你才能从namespace外部访问方法和变量。

基本用法

请看下面的栗子:

nsTest.ts文件内容如下:

namespace tsNamespace {

let ownerName: string = "tsNameSpace";

export function sayHello(name: string) {

console.log(ownerName, "Hello,", name);

}

}

namespace tsNamespace2 {

let ownerName: string = "tsNamespace2"

export function sayHello(name: string) {

console.log(ownerName, "Hello,", name);

}

export interface UserInfo {

name: string;

age: number;

}

export namespace tsNamespace22 {

export const MAX: number = 1000;

export class Person {

private _name: string = "aaa";

private _sex: string = "未知";

getName(): string {

return this._name;

}

getSex(): string {

return this._sex;

}

}

}

}

tsNamespace.sayHello("Andy");

tsNamespace2.sayHello("Andy");

let userInfo: tsNamespace2.UserInfo = { name: "andy", age: 25 };

console.log(userInfo);

let tsNameSpace22 = tsNamespace2.tsNamespace22;

console.log(tsNameSpace22.MAX);

let Person = tsNamespace2.tsNamespace22.Person;

let person = new Person();

console.log(person);

console.log(person.getName());

console.log(person.getSex());

运行截图:

image-20201107230609316

可以看到在这里我定义了两个namespace,他们之间有相同的方法,但是互不影响,如果没有放在不同的namespace中,会报错。这也就印证了namespace的作用。

还有就是namespace的用法,在tsNamespace2中,namespace可以包含变量、函数、接口、类等等一系列东西,并且namespace还可以嵌套定义,namespace中还可以定义namespace。那么访问其中的变量、函数、接口等的方法是,在他们前面都加上export(表示可以导出,外部可用),然后通过namespace调用.运算符即可调用。

namespace的定义可以分多文件

当应用变得越来越大时,我们需要将代码分离到不同的文件中以便于维护。请看下面的栗子:

nsTest2.ts内容如下:

namespace tsNamespace2 {

export function sayHi(name: string) {

console.log("Hi,", name);

}

export namespace tsNamespace100 {

export interface UserInfo {

nickName: string;

age: number;

sex: string;

}

}

}

结合上面的代码,可以看到在nsTest.ts中定义了tsNamespace2,在nsTest2.ts中也定义了tsNamespace2。

在nsTest.ts中追加以下代码:

tsNamespace2.sayHi("Leo");

import tsNamespace100 = tsNamespace2.tsNamespace100;

let user: tsNamespace100.UserInfo = { nickName: "天下无双", age: 12, sex: "男" };

console.log(user);

然后用tsc编译,输入

tsc --outfile test.js nsTest2.ts nsTest.ts

注意这里 nsTest2.ts nsTest.ts这是一个编译顺序列表。

要为了确保调用sayHi是在定义tsNamespace2的sayHi之后,要不然会出错。原则:调用之前,必须先定义

运行结果如下:

image-20201107234506841

可以知道,namespace的定义是可以分多文件的。

注意一点:定义namespace时,其中的方法都必须实现。

在声明(declare)namespace时,又是不能实现具体的方法。

如何应用写好的namespace?

第一种是用reference

在文件中开头加入 ///

注意事项三个 / 哦

通过reference进行导入相当于xxx.ts文件内的命名空间和当前文件进行了合并。

nsTest3.ts:

image-20201108185624857

nsTest4.ts:

image-20201108185719936

nsTest999.ts:

image-20201108185800698

运行截图:

image-20201108190032685

第二种是用import

如果命名空间是用export导出的, 那么使用的时候就不可以用/// 了, 要用import导入。

写法如下:

image-20201108193511534

如有错误,还请提出。一起学习,共同成长。

### TypeScript 命名空间的适用情况 当处理较小规模的应用程序或特定功能模块时,如果希望避免全局命名污染并保持代码整洁有序,则可以考虑使用命名空间。然而,在现代Web开发实践中更倾向于采用ES6模块化方案[^3]。 对于遗留系统的迁移工作而言,利用命名空间能够逐步过渡到更加现代化的架构设计模式下而不至于一次性重构整个项目结构;另外,在某些特殊场合比如编写第三方库的时候也可以借助命名空间来封装内部实现细节从而保护私有成员不受外界干扰[^1]。 ### 使用场景示例 #### 场景一:防止变量冲突 假设在一个页面中有多个独立的功能区域都需要定义名为`User`的对象类型: ```typescript // 定义第一个命名空间中的 User 类型 namespace AdminPanel { export interface User { id: number; username: string; role: "admin"; } } // 定义第二个命名空间中的 User 类型 namespace PublicSite { export class User { constructor(public name: string, public email?: string) {} } } ``` 通过这种方式可以在不引起任何名称冲突的情况下分别创建两个具有相同名字但含义不同的实体[^4]。 #### 场景二:模拟类继承关系 有时为了简化依赖注入过程或者模仿面向对象编程里的继承机制,可以通过嵌套的方式构建层次化的命名空间体系: ```typescript namespace Shapes { export namespace Circle { export function draw(radius: number): void { console.log(`Drawing circle with radius ${radius}`); } } export namespace Rectangle { export function draw(width: number, height: number): void { console.log(`Drawing rectangle of width=${width},height=${height}`); } } } Shapes.Circle.draw(5); // Drawing circle with radius 5 Shapes.Rectangle.draw(10,20);// Drawing rectangle of width=10,height=20 ``` 上述例子展示了如何基于几何图形这一主题建立起一组相互关联却又各自独立存在的子命名空间集合。 ### 最佳实践建议 - **谨慎选用**:尽管命名空间有助于解决一些实际问题,但由于其局限性和潜在风险(如增加理解成本),除非必要否则应优先尝试其他解决方案例如ES Modules; - **合理规划**:一旦决定引入命名空间特性就要做好充分准备,包括但不限于提前构思好整体布局框架、制定清晰易懂的名字约定规则等措施以确保后续维护工作的顺利开展; - **适度运用**:即使是在适合应用命名空间的情境里也应当控制好数量范围以免过度分隔而导致难以追踪调试等问题的发生; - **文档记录**:及时更新相关说明文件以便团队成员之间共享知识经验共同进步。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值