TypeScript中的内部模块和外部模块有什么区别?
我花了一些时间阅读Typescript语言规范,并对内部和外部模块之间的差异感到有些困惑。 这是直接来自规范的描述:
内部模块(第9.2.2节)是其他模块(包括全局模块和外部模块)的本地或导出成员。 内部模块使用指定其名称和主体的ModuleDeclarations进行声明。 具有多个标识符的名称路径等效于一系列嵌套的内部模块声明。
外部模块(第9.4节)是使用外部模块名称引用的单独加载的代码体。 外部模块被编写为一个单独的源文件,其中至少包含一个导入或导出声明。 另外,可以使用全局模块中的AmbientModuleDeclarations声明外部模块,该声明直接将外部模块名称指定为字符串文字。 这将在第0节中进一步描述。
根据我的理解,我认为外部模块对应于打字稿文件,而没有包含仅导出一组类型和/或变量的模块定义。 从另一个打字稿文件中,我可以使用import foo = module("foo");
简单地在foo.ts中导入外部模块
有人可以向我解释外部模块和内部模块之间的区别吗?
规范的9.3和9.4节对此进行了更清晰的说明。 我将在此重现这些部分中给出的一些示例。
外部模块
假设以下代码在main.ts
中。
import log = module("log");
log.message("hello");
该文件引用外部模块module
,该模块由module
导出的内容定义。
export function message(s: string) {
console.log(s);
}
请注意,module
不在任何地方使用module
关键字。 它只输出export
。
内部模块
该文件具有两个内部模块module
。
module A.B.C {
import XYZ = X.Y.Z;
export function ping(x: number) {
if (x > 0) XYZ.pong(x – 1);
}
}
module X.Y.Z {
import ABC = A.B.C;
export function pong(x: number) {
if (x > 0) ABC.ping(x – 1);
}
}
它们的行为(大部分)类似于外部模块,但是它们包含在一个文件中,您不必引用任何外部文件即可使用它们。 定义它们时,它们必须包含在module
块中。
根据Anders的演示文稿:[http://channel9.msdn.com/posts/Anders-Hejlsberg-Introducing-TypeScript](34:40)和Typescript文档,外部模块是基于顶级AMD(异步模型定义)的模块 )或CommonJS。
外部模块在某种意义上很有用,因为它们隐藏了模块定义的内部语句,并且仅显示与声明的变量关联的方法和参数。
假设您有一个Main
类,并将定义的log
方法放置在transfer.js
文件中。 仅当在源js文件顶部导入transfer.js
文件时,Main
类的内部方法才可见:///<reference path="transfer.js"/>
。这样,编译器消除了运行时对所有js文件的遍历。
这是使用外部模块的巨大好处。 另一个是当您尝试引用外部方法或类时,该方法或类在正常的自上而下的javascript流中定义的时间比方法调用晚。 使用外部模块,仅在方法调用时实例化引用的类。
内部模块:
- 您可以在打字稿文件中定义模块。
- 在模块内定义的所有变量都将作用域限定在模块内,并从全局作用域中删除。
- 编译打字稿文件时,模块将转换为变量,这些变量根据需要嵌套以形成类似名称空间的对象。 请注意,使用IIFE(立即调用函数表达式)将模块内定义的类完全隔离。
- 下面的代码显示MyClass变量的作用域为MyInternalModule模块。 无法在模块外部访问它们,这就是为什么代码的最后一行显示错误无法找到名称MyClass的原因。
- 您可以使用export关键字在模块外部访问变量。
- 您还可以扩展内部模块,在文件之间共享它们以及使用三斜杠语法引用它们。(///)
例:
module MyInternalModule{
class MyClass{ //if We write export keyword before the MyClass then last line works fine
constructor (
public height: number,
public width: number) {
}
}
//working properly
var obj1 = new MyClass(10, 4);
}
// it wont work //Because the out of the scope
var obj2 = new MyInternalModule.MyClass(10,4) //shows error: can not find name MyClass
Typescript的编译版本:
var MyInternalModule;
(function (MyInternalModule) {
var MyClass = (function () {
function MyClass(height, width) {
this.height = height;
this.width = width;
}
return MyClass;
})();
//working properly
var obj1 = new MyClass(10, 4);
})(MyInternalModule || (MyInternalModule = {}));
外部模块:
例:
// bootstrapper.ts file
// imports the greeter.ts file as the greeter module
import gt = module('greeter');
export function run() {
var el = document.getElementById('content');
var greeter = new gt.Greeter(el);
greeter.start();
}
// greeter.ts file
// exports the entire module
export class Greeter {
start() {
this.timerToken = setInterval(() =>
this.span.innerText =
new Date().toUTCString(), 500);
}
}