从 0 开始的 TypeScriptの十一:模块和命名空间
模块
JavaScript 先天缺少一项功能:模块。 所以在es6
提出的Module
模块的概念,当然在nodeJs
中也存在CommonJS
规范。
在typescript
中的主要模块概念还是Module
模块
模块在其自身的作用域里执行,而不是在全局作用域里;这意味着定义在一个模块里的变量,函数,类等等在模块外部是不可见的,除非你明确地使用export
形式之一导出它们。
相反,如果想使用其它模块导出的变量,函数,类,接口等的时候,你必须要导入它们,可以使用import
形式之一。
模块是自声明的;两个模块之间的关系是通过在文件级别上使用imports
和exports
建立的。
模块使用模块加载器去导入其它的模块。 在运行时,模块加载器的作用是在执行此模块代码前去查找并执行这个模块的所有依赖。
任何包含顶级import
或者export
的文件都被当成一个模块。相反地,如果一个文件不带有顶级的import
或者export
声明,那么它的内容被视为全局可见的(因此对模块也是可见的)。
在大型项目中,肯定需要模块化,不然仅仅是
typescript
的命名冲突就够报一堆错误了
当然,这里如果在文件中使用
import
或者export
会产生一个问题。 使用tsc
转换后的 js 并不能在浏览器中直接使用,因为不支持。 所以这里可以采用webpack
打包转换
导出 exports
任何声明(比如变量,函数,类,类型别名或接口)都能够通过添加export
关键字来导出。
方式:
export var a:number = 10;
export { a };
export default a;
注意: export default 在一个模块中只能使用一次,并且导入不能使用 {},可以直接在 import 后写名称
例子
a.ts:
b.ts: 使用 import 进行引入时,可以省略引入文件的后缀
此时运行 tsc b.ts
命令,会同时生成a.js
和b.js
两个 JavaScript 文件。 可以使用node b.js
来运行,打印 9;
可选的模块加载
编译器会检测是否每个模块都会在生成的 JavaScript 中用到。 如果一个模块标识符只在类型注解部分使用,并且完全没有在表达式中使用时,就不会生成 require 这个模块的代码。 省略掉没有用到的引用对性能提升是很有益的,并同时提供了选择性加载模块的能力。
这种模式的核心是import id = require("...")
语句可以让我们访问模块导出的类型。 模块加载器会被动态调用(通过 require)。 它利用了省略引用的优化,所以模块只在被需要时加载。
命名空间
在代码量较大的情况下,为了避免各种变量命名相冲突,可将相似功能的函数、接口、类等放置到命名空间内
TypeScript
的命名空间可以将代码包裹起来,只对外暴露需要在外部访问的对象,空间中的对象通过export
进行抛出 (这和上面的模块就很相像了,所以 TypeScript 1.5 之前属于名称是“内部模块”)
TypeScript
中命名空间使用 namespace
来定义
命名空间和模块的区别:
命名空间主要防止命名冲突
模块是 ts 外部模块的简称,侧重于代码的复用
一个模块里可能会有多个命名空间
命名空间
下面编写一个例子:
这就是一个简单是命名空间,在空间外部对于空间内 Animal 类的使用方法
其实命名空间namespace
在经过 tsc 编译后,会变成像下面一样的匿名函数
命名空间别名
在使用命名空间时,可能会需要简化空间名称,这是可以使用import 别名 = 命名空间
的方式来取一个别名
注意: 这里给命名空间取别名的
import
和导入模块的import
是不一样的
给上面的例子中First
命名空间取别名:
版权声明: 本文为 InfoQ 作者【空城机】的原创文章。
原文链接:【http://xie.infoq.cn/article/34be175d4bdd16695f340aeef】。文章转载请联系作者。
评论