TypeScript 从入门到放弃(三):模块、命名空间、声明合并、声明文件

TypeScript 从入门到放弃(三):模块、命名空间、声明合并、声明文件
镇长前言
本文作为学习笔记,文中内容大多来自官方文档和一些资料,摘抄的部分会在文中标注出原文地址,可以直接参考原文。
前两篇学习了 TS 中基本类型、函数、类、接口、泛型以及高级类型概念和使用方法。这些是基础知识点,虽然简单但是很重要。本文将复习 JS 中的模块对比不同方式模块的区别;如何使用命名空间隔离代码;声明合并的规则等。
模块
在 ES6 之前采用的模块加载方案,主要有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。ES6 在此基础上实现了模块的功能,使用简单可以完全取代之前的方案,成为浏览器和服务器通用的模块解决方案。
下面学习 ES6 中模块的导出和导入。
导出
ES6 提供了多种导出方式,例如:单独导出,批量导出、导出接口/函数、导出起别名、默认导出以及复合导出等。
导出使用 export命令,举个例子:
1 | // a.js |
导入
对应着 export 命令,导入使用 import 命令。
1 | // 导入 |
关于 ES6 模块可以参考:阮一峰老师《ES6入门》
浏览器加载
默认情况下,浏览器是同步加载 JS 脚本,遇到 <script> 标签会等待执行完脚本才会继续渲染。在文件较大下载和执行时间较长时,会出现浏览器假死无响应。为了解决这个问题,加入异步加载语法。在 <script>中使用defer和async属性,指定脚本异步加载。
defer: 渲染完在执行。要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),才会执行。async: 下载完就执行。一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。
在浏览器中加载模块需要将 type 指定为 module。
1 | <script type="module" src="a.js"/> |
指定 type="module" 的 <script> 都是异步的。
ES6 模块和 CommonJS 模块的区别
ES6 模块和 CommonJS 是完全不同的。
CommonJS模块输出的是一个值的拷贝,ES6模块输出的是值的引用。CommonJS模块是运行时加载的,ES6模块时编译时输出接口。
拷贝值和值引用的最大区别是:值拷贝时原始值改变拷贝值不会变,值引用则会随原始值改变。
举个例子:
1 | // b.js |
上面的例子输出结果是多少?
b.js 是一个模块导出一个变量 counter 和一个函数 incCounter。
首次输出 counter 值为 3。当调用 b.incCounter 函数后再输出 counter 仍为 3。导致 counter 不改变的原因 CommonJS 模块是值拷贝。
同样的例子在 ES6 模块中就不会出现这个问题。
1 | // a.js |
以上是 ES6 模块和 CommonJS 模块的区别。具体可以参考阮一峰老师《ES6入门-模块加载》
TS 中模块
为了支持 CommonJS 的 exports, TS 提供了 export= 语法。export= 语法定义一个模块的导出对象。 这里的对象一词指的是类,接口,命名空间,函数或枚举。若使用export=导出一个模块,则必须使用 TS 的特定语法import module = require("module")来导入此模块。
命名空间
命名空间用来解决重名问题,定义命名空间使用 namespace 关键字。
1 | namespace Shape { |
定义了一个 Shape 命名空间,向外部提供了一个 Square 函数,使用 export 关键字导出。调用的方法是 Shape.square(1) 直接使用命名空间调用。
引入命名空间的方法比较特殊,格式如下:
1 | /// <reference path="shape.ts"/> |
使用 /// 引用命名空间。
声明合并
声明合并是指编译器将同名的独立声明合并为单个声明。合并后的声明拥有原来多个声明的特性。
接口的声明合并
1 | interface A { |
两个地方声明同样的接口时,编译器会自动合并到一起。当相同属性类型不同是会提示错误。
命名空间的声明合并
1 | namespace Animals { |
命名空间合并的是导出成员,非导出成员是无法被合并访问的。
函数与命名空间合并
1 | // 命名空间和函数的合并 |
可以使用函数和命名空间合并的方式,为函数添加属性。
注意:函数的声明必须在命名空间前。
类与命名空间合并
1 | // 命名空间和类合并 |
使用合并为类添加一些静态的属性。
注意:类的定义必须在命名空间前。
枚举与命名空间合并
1 | // 命名空间和枚举合并 |
注意:和类与函数不同,枚举可以放在命名空间的后面。
声明文件
当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能。
声明文件通过 declare 关键字告诉 TS,正在表述其他地方已经存在的代码。
小结
以上是本篇的全部内容,都是一些比较基础的知识点,后续随着学习的深入在慢慢补充。











