TypeScript学习笔记(八):1.5版本之后的模块和命名空间
2017-05-24 19:18
483 查看
我之前有写过TS1.5版本之前的“模块”的笔记:TypeScript学习笔记(七):模块
但是TS这里的模块和在ECMAScript 2015里的模块(即JS原生支持了模块的概念)概率出现了混淆,所以在1.5的版本里,为了与ECMAScript 2015里的术语保持一致,“内部模块”现在称做“命名空间”,“外部模块”现在则简称为“模块”。
下面摘录自Egret博客的一段详细解释(连接):
大体意思就是 TS1.5 以后,推荐全面使用namespace关键字代替module。因为JS里本身就有module的概念,而且已经是ES6标准里的关键字,各种加载框架比如CommonJS,AMD等也都有module的概念,但是TS里之前的module关键字与他们都不太相同。所以换了一个关键字加以区分,避免造成概念上的混淆。实际语法上,使用namespace等价于TS以前使用的module,然后推荐代码中不要再出现module关键字,这个关键字基本上变成了一个编译后和运行时里的概念,留给纯JS中使用。
如果要用一句话解释TS里的namespace与JS里module的区别,那主要在于文件上:TS里的namespace是跨文件的,JS里的module是以文件为单位的,一个文件一个module。
TS里的namespace主要是解决命名冲突的问题,会在全局生成一个对象,定义在namespace内部的类都要通过这个对象的属性访问,例如 egret.DisplayObject,egret就是namespace的对象,DisplayObject则是那个类名。因为是注册到全局的,所以跨文件也能正常使用,不同的文件能够读取其他文件注册在全局的命名空间内的信息,也可以注册自己的。namespace其实比较像其他面向对象编程语言里包名的概念。
而JS里的module,主要是解决加载依赖关系的。跟文件绑定在一起,一个文件就是一个module。在一个文件中访问另一个文件必须要加载另一个文件。在NodeJS里是用CommonJS处理模块加载,因为是运行在本地,所以可以同步加载,写起来也比较方便。用到一个文件就require它一下,作为一个变量。而在Web端的RequireJS使用的是AMD处理模块加载,是异步的。其实就是把所有代码写在回调里,先去异步加载依赖的所有文件。
所以可以简单的理解,namespace的概念等同于包名,module的概念等同于文件。
下面我们来分别看看。
另外对于存在依赖关系的文件,仍然可以使用:
方式来指定当前文件依赖的其它文件。
其中的module表示模块使用的标准,默认是CommonJS标准。
注意不要使用module或namespace进行包含,直接使用export导出即表示要导出到外部可以访问的对象。
使用模块代码,App.ts:
使用TS的导入写法即可,详情点击这里。
App.js:
上面生成的代码可以在Node.js中使用。
编译之后,Utils.js:
App.js:
上面的代码可以在浏览器中使用,注意要引入require.js库就行。
但是TS这里的模块和在ECMAScript 2015里的模块(即JS原生支持了模块的概念)概率出现了混淆,所以在1.5的版本里,为了与ECMAScript 2015里的术语保持一致,“内部模块”现在称做“命名空间”,“外部模块”现在则简称为“模块”。
下面摘录自Egret博客的一段详细解释(连接):
大体意思就是 TS1.5 以后,推荐全面使用namespace关键字代替module。因为JS里本身就有module的概念,而且已经是ES6标准里的关键字,各种加载框架比如CommonJS,AMD等也都有module的概念,但是TS里之前的module关键字与他们都不太相同。所以换了一个关键字加以区分,避免造成概念上的混淆。实际语法上,使用namespace等价于TS以前使用的module,然后推荐代码中不要再出现module关键字,这个关键字基本上变成了一个编译后和运行时里的概念,留给纯JS中使用。
如果要用一句话解释TS里的namespace与JS里module的区别,那主要在于文件上:TS里的namespace是跨文件的,JS里的module是以文件为单位的,一个文件一个module。
TS里的namespace主要是解决命名冲突的问题,会在全局生成一个对象,定义在namespace内部的类都要通过这个对象的属性访问,例如 egret.DisplayObject,egret就是namespace的对象,DisplayObject则是那个类名。因为是注册到全局的,所以跨文件也能正常使用,不同的文件能够读取其他文件注册在全局的命名空间内的信息,也可以注册自己的。namespace其实比较像其他面向对象编程语言里包名的概念。
而JS里的module,主要是解决加载依赖关系的。跟文件绑定在一起,一个文件就是一个module。在一个文件中访问另一个文件必须要加载另一个文件。在NodeJS里是用CommonJS处理模块加载,因为是运行在本地,所以可以同步加载,写起来也比较方便。用到一个文件就require它一下,作为一个变量。而在Web端的RequireJS使用的是AMD处理模块加载,是异步的。其实就是把所有代码写在回调里,先去异步加载依赖的所有文件。
所以可以简单的理解,namespace的概念等同于包名,module的概念等同于文件。
下面我们来分别看看。
命名空间
把之前的module关键字换成namespace关键字即可,使用方法和功能都不变,类似Java的包或C#的命名空间。当然,不替换或者继续使用module关键字也是可以的,但是会出现概念混淆的情况,最好按照官方的说法,统一使用namespace吧,包括*.d.ts文件。另外对于存在依赖关系的文件,仍然可以使用:
/// <reference path="SimpleWebSocket.ts"/>
方式来指定当前文件依赖的其它文件。
模块
TS中,对模块也是支持的,如果对JS的模块不熟悉可以查看这篇笔记。使用什么标准
我们知道JS中模块有多种标准,一般常用的有两种,针对Node.js同步加载的CommonJS,和针对浏览器异步加载的AMD,在TS项目中,有一个tsconfig.json的文件,一般如下:{ "compilerOptions": { "module": "commonjs", "target": "es5", "sourceMap": true }, "exclude": [ "node_modules" ] }
其中的module表示模块使用的标准,默认是CommonJS标准。
TS模块代码
模块代码,Utils.ts:export const version: number = 0.1; export class Utils { static add(a: number, b: number): number { return a + b; } private _name: string; constructor(name: string) { this._name = name; } sayHi(): void { console.log("Hi, I am " + this._name); } }
注意不要使用module或namespace进行包含,直接使用export导出即表示要导出到外部可以访问的对象。
使用模块代码,App.ts:
import * as utils from "./Utils"; console.log(utils.version); var obj = new utils.Utils("Li Lei"); obj.sayHi();
使用TS的导入写法即可,详情点击这里。
CommonJS编译后的代码
Utils.js:"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.version = 0.1; var Utils = (function () { function Utils(name) { this._name = name; } Utils.add = function (a, b) { return a + b; }; Utils.prototype.sayHi = function () { console.log("Hi, I am " + this._name); }; return Utils; }()); exports.Utils = Utils;
App.js:
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var utils = require("./Utils"); console.log(utils.version); var obj = new utils.Utils("Li Lei"); obj.sayHi();
上面生成的代码可以在Node.js中使用。
AMD编译后的代码
先修改tsconfig.json如下:{ "compilerOptions": { "module": "amd", "target": "es5", "sourceMap": true }, "exclude": [ "node_modules" ] }
编译之后,Utils.js:
define(["require", "exports"], function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.version = 0.1; var Utils = (function () { function Utils(name) { this._name = name; } Utils.add = function (a, b) { return a + b; }; Utils.prototype.sayHi = function () { console.log("Hi, I am " + this._name); }; return Utils; }()); exports.Utils = Utils; });
App.js:
define(["require", "exports", "./Utils"], function (require, exports, utils) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); console.log(utils.version); var obj = new utils.Utils("Li Lei"); obj.sayHi(); });
上面的代码可以在浏览器中使用,注意要引入require.js库就行。
相关文章推荐
- PetShop 4.0 设计研究——petShop 4.0 的命名空间 以及各个项目模块的说明
- PetShop 4.0 设计研究——petShop 4.0 的命名空间 以及各个项目模块的说明
- python学习笔记——模块和命名空间
- JS模块与命名空间的介绍
- JS模块与命名空间的介绍
- PetShop 4.0 设计研究——petShop 4.0 的命名空间 以及各个项目模块的说明
- MVC4项目中(.net 4.5)区域模块中 报错 “System.Web”中不存在类型或命名空间名称“Optimization”
- JavaScript重构(一):模块划分和命名空间 收藏
- .Net Framework 版本引起的找不到命名空间
- JDOM2.0.5版本通过xpath读取xml或读取带有命名空间的xml
- PetShop 4.0 设计研究——petShop 4.0 的命名空间 以及各个项目模块的说明
- PetShop 4.0 设计研究——petShop 4.0 的命名空间 以及各个项目模块的说明
- 模块(Module)的用途1 命名空间(Namespace)
- SPORE,一个很好的实现JS命名空间的管理,模块的定义,与自动加载依赖模块的脚本文件
- PetShop 4.0 设计研究——petShop 4.0 的命名空间 以及各个项目模块的说明
- PetShop 4.0 设计研究——petShop 4.0 的命名空间 以及各个项目模块的说明
- PetShop 4.0 设计研究——petShop 4.0 的命名空间 以及各个项目模块的说明
- petShop 4.0 的命名空间 以及各个项目模块的说明
- Android各个版本命名(从1.5到6.0)
- js模块,类,继承,命名空间,私有属性等相关概念梳理