TypeScript學習筆記(八):1.5版本之后的模塊和命名空間


我之前有寫過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關鍵字換成namespace關鍵字即可,使用方法和功能都不變,類似Java的包或C#的命名空間。當然,不替換或者繼續使用module關鍵字也是可以的,但是會出現概念混淆的情況,最好按照官方的說法,統一使用namespace吧,包括*.d.ts文件。

另外對於存在依賴關系的文件,仍然可以使用:

/// <reference path="SimpleWebSocket.ts"/>

方式來指定當前文件依賴的其它文件。

模塊

TS中,對模塊也是支持的,如果對JS的模塊不熟悉可以查看這篇筆記

使用什么標准

我們知道JS中模塊有多種標准,一般常用的有兩種,針對Node.js同步加載的CommonJS,和針對瀏覽器異步加載的AMD,在TS項目中,有一個tsconfig.json的文件,一般如下:

 1 {
 2   "compilerOptions": {
 3     "module": "commonjs",
 4     "target": "es5",
 5     "sourceMap": true
 6   },
 7   "exclude": [
 8     "node_modules"
 9   ]
10 }

其中的module表示模塊使用的標准,默認是CommonJS標准。

TS模塊代碼

模塊代碼,Utils.ts:

 1 export const version: number = 0.1;
 2 
 3 export class Utils {
 4     static add(a: number, b: number): number {
 5         return a + b;
 6     }
 7 
 8     private _name: string;
 9 
10     constructor(name: string) {
11         this._name = name;
12     }
13 
14     sayHi(): void {
15         console.log("Hi, I am " + this._name);
16     }
17 }

注意不要使用module或namespace進行包含,直接使用export導出即表示要導出到外部可以訪問的對象。

使用模塊代碼,App.ts:

1 import * as utils from "./Utils";
2 
3 console.log(utils.version);
4 
5 var obj = new utils.Utils("Li Lei");
6 obj.sayHi();

使用TS的導入寫法即可,詳情點擊這里

CommonJS編譯后的代碼

Utils.js:

 1 "use strict";
 2 Object.defineProperty(exports, "__esModule", { value: true });
 3 exports.version = 0.1;
 4 var Utils = (function () {
 5     function Utils(name) {
 6         this._name = name;
 7     }
 8     Utils.add = function (a, b) {
 9         return a + b;
10     };
11     Utils.prototype.sayHi = function () {
12         console.log("Hi, I am " + this._name);
13     };
14     return Utils;
15 }());
16 exports.Utils = Utils;

App.js:

1 "use strict";
2 Object.defineProperty(exports, "__esModule", { value: true });
3 var utils = require("./Utils");
4 console.log(utils.version);
5 var obj = new utils.Utils("Li Lei");
6 obj.sayHi();

上面生成的代碼可以在Node.js中使用。

AMD編譯后的代碼

先修改tsconfig.json如下:

 1 {
 2   "compilerOptions": {
 3     "module": "amd",
 4     "target": "es5",
 5     "sourceMap": true
 6   },
 7   "exclude": [
 8     "node_modules"
 9   ]
10 }

編譯之后,Utils.js:

 1 define(["require", "exports"], function (require, exports) {
 2     "use strict";
 3     Object.defineProperty(exports, "__esModule", { value: true });
 4     exports.version = 0.1;
 5     var Utils = (function () {
 6         function Utils(name) {
 7             this._name = name;
 8         }
 9         Utils.add = function (a, b) {
10             return a + b;
11         };
12         Utils.prototype.sayHi = function () {
13             console.log("Hi, I am " + this._name);
14         };
15         return Utils;
16     }());
17     exports.Utils = Utils;
18 });

App.js:

1 define(["require", "exports", "./Utils"], function (require, exports, utils) {
2     "use strict";
3     Object.defineProperty(exports, "__esModule", { value: true });
4     console.log(utils.version);
5     var obj = new utils.Utils("Li Lei");
6     obj.sayHi();
7 });

上面的代碼可以在瀏覽器中使用,注意要引入require.js庫就行。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM