命名空间是一种用于组织和分类代码的 TypeScript 特定方式,使你能够将相关代码组合在一起。
可以使用命名空间执行以下操作:
减少全局范围内的代码量,限制“全局范围污染”。
为名称提供上下文,有助于减少命名冲突。
提高可重用性。
如果要使函数或类可供命名空间之外的代码使用,请在其名称前面添加 export 关键字。
如果省略 export 关键字,则只能在命名空间内使用该组件。
若要在命名空间中使用类或函数,请为组件名称添加命名空间名称前缀。
namespace?A?{
????export?function?fun1(msg:?string)?{
????????console.log(`空间A的方法1?${msg}.`);
????}
}
namespace?B?{
????export?function?fun1(msg:?string)?{
????????console.log(`空间B的方法1?${msg}.`);
????}
}
A.fun1('Hello');?//?输出:空间A的方法1?Hello.
B.fun1('Hello');?//?输出:空间B的方法1?Hello.
namespace?A?{
????export?function?fun1(msg:?string)?{
????????console.log(`空间A的方法1?${msg}.`);
????}
????export?namespace?A1?{
????????export?function?fun2(msg:?string)?{
????????????console.log(`空间A的空间A1方法2?${msg}`);
????????}
????}
????namespace?A2?{
????????export?function?fun2(msg:?string)?{
????????????console.log(`空间A的空间A1方法2?${msg}`);
????????}
????}
}
namespace?B?{
????export?function?fun1(msg:?string)?{
????????console.log(`空间B的方法1?${msg}.`);
????}
}
A.fun1('Hello');?//?输出:空间A的方法1?Hello.
B.fun1('Hello');?//?输出:空间B的方法1?Hello.
A.A1.fun2('Hello');?//?输出:空间A的空间A1方法2?Hello
A.A2.fun2('Hello');?//?未导出空间?报错?类型“typeof?A”上不存在属性“A2”。
随着嵌套命名空间变得越来越复杂,你可能需要创建一个别名来缩短和简化代码。 为此,请使用 import 关键字。
import?A1?=?A.A1;
A1.fun2('HelloA1');?//?输出:空间A的空间A1方法2?Hello
可以通过跨多个 TypeScript 文件共享命名空间来扩展它们。 使用三斜杠 (///) 语法 告诉 TypeScript 文件直接的关系 比如有下面三个文件:
interfaces.ts,它声明包含某些接口定义的命名空间。
functions.ts,该文件使用在 interfaces.ts 中实现接口的函数声明命名空间。
main.ts,它调用 functions.ts 中的函数,并表示应用程序的主代码。
如果对多个文件进行引用,请从最高级别的命名空间开始,然后逐渐向下。 在编译文件时,TypeScript 将使用此顺序。
方法1 每个文件编译
默认情况下,当你在 main.ts 上运行 TypeScript 编译器时,它将检查文件中的 reference 语句,并为每个输入文件生成一个 JavaScript 文件。 如果选择此选项,请使用网页上的 <script> 标记按相应顺序加载每个发出的文件。
方法2 单一文件编译
还可以使用 --outFile 选项指示编译器生成单个 JavaScript 输出文件。 在上面的示例中,命令 tsc --outFile main.js main.ts 指示编译器生成一个名为 main.js 的 JavaScript 文件。
可以将命名空间或模块用于代码组织,两者都可以包含代码和声明。
虽然命名空间易于用于简单实现并且不依赖于模块加载器,但模块还提供了一些命名空间所没有的其他好处。 模块:
声明它们的依赖项。
提供更好的代码重用。
提供强大的隔离。
隐藏模块定义的内部语句,并仅显示与声明的组件相关联的方法和参数。
为捆绑提供更好的工具支持。
建议用于 Node.js 应用程序的命名空间,因为模块是默认的。
可以解决自上而下的 JavaScript 流问题,因为对外部方法或类的引用仅在方法调用中实例化。
从 ECMAScript 2015 开始,模块是语言的原生部分,所有符合的引擎实现都应支持模块。 因此,对于新项目,建议对代码组织使用模块。
不建议将命名空间和模块合并到同一个项目中。
模块 | 命名空间 |
---|---|
使用模块将代码组织到单独的文件中,以便对功能进行逻辑分组。 | 使用命名空间将代码组织到单独的文件中,以便对功能进行逻辑分组。 |
模块在其本地范围内执行,而不是在全局范围内执行。 | 命名空间在其本地范围内执行,而不是在全局范围内执行。 |
模块是声明性的;模块之间的关系是根据文件级的导入和导出进行指定的。 | 命名空间不能声明其依赖项。 |
可以通过在文件中使用 export 或 import 关键字来定义模块。 包含顶级导入或导出的任何文件都视为模块。 | 通过在文件中使用 namespace 关键字来定义命名空间。 命名空间语句可以嵌套并跨越多个文件。 |
若要在模块外公开单独的模块组件,请使用 export 关键字。 | 若要在命名空间外公开单独的命名空间组件,请使用 export 关键字。 |
若要在一个模块中使用另一个模块中的组件,请使用 import 关键字。 | 若要在另一个 TypeScript 文件中使用一个命名空间中的组件,请使用三斜杠 (///) 语法来添加 reference 语句。 |
若要编译模块及其所有从属文件,请使用 tsc --module 命令。 | 若要将包含命名空间及其所有从属文件的 TypeScript 文件编译为单独的 JavaScript 文件,请使用 tsc 命令。 |
不能将多文件模块编译为单个模块。 | 若要将包含命名空间的所有 TypeScript 文件编译为单个 JavaScript 文件,请使用 tsc --outFile 命令。 |
模块使用模块加载器 API 导入另一个模块。 编译模块时,需要指定 API。 | 命名空间是通过在 HTML 页中使用 <script> 标记指定 .js 文件名(按顺序)进行加载的。 |
在模块中,你可以使用原始名称重新导出组件或对其进行重命名。 | 在命名空间中,无法重新导出或重命名组件。 |
将代码添加到命名空间时会发生什么情况??
将从全局命名空间中删除声明。( 命名空间从全局命名空间中删除声明,为名称提供上下文,并有助于减少命名冲突。)