TypeScript——模塊(1)

從ECMAScript 2015開始,JavaScript引入了模塊的概念。TypeScript也沿用這個(gè)概念。

模塊在其自身的作用域里執(zhí)行,而不是在全局作用域里;這意味著定義在一個(gè)模塊里的變量,函數(shù),類等等在模塊外部是不可見的,除非你明確地使用export形式之一導(dǎo)出它們。 相反,如果想使用其它模塊導(dǎo)出的變量,函數(shù),類,接口等的時(shí)候,你必須要導(dǎo)入它們,可以使用 import形式之一。

模塊是自聲明的;兩個(gè)模塊之間的關(guān)系是通過在文件級別上使用imports和exports建立的。

模塊使用模塊加載器去導(dǎo)入其它的模塊。 在運(yùn)行時(shí),模塊加載器的作用是在執(zhí)行此模塊代碼前去查找并執(zhí)行這個(gè)模塊的所有依賴。 大家最熟知的JavaScript模塊加載器是服務(wù)于Node.js的 CommonJS和服務(wù)于Web應(yīng)用的Require.js。

TypeScript與ECMAScript 2015一樣,任何包含頂級import或者export的文件都被當(dāng)成一個(gè)模塊。相反地,如果一個(gè)文件不帶有頂級的import或者export聲明,那么它的內(nèi)容被視為全局可見的(因此對模塊也是可見的)。

導(dǎo)出

導(dǎo)出聲明

任何聲明(比如變量,函數(shù),類,類型別名或接口)都能夠通過添加export關(guān)鍵字來導(dǎo)出。

Validation.ts

export interface StringValidator {

? ? isAcceptable(s: string): boolean;

}

ZipCodeValidator.ts

export const numberRegexp = /^[0-9]+$/;

export class ZipCodeValidator implements StringValidator {

? ? isAcceptable(s: string) {

? ? ? ? return s.length === 5 && numberRegexp.test(s);

? ? }

}

導(dǎo)出語句

導(dǎo)出語句很便利,因?yàn)槲覀兛赡苄枰獙?dǎo)出的部分重命名,所以上面的例子可以這樣改寫:

class ZipCodeValidator implements StringValidator {

? ? isAcceptable(s: string) {

? ? ? ? return s.length === 5 && numberRegexp.test(s);

? ? }

}

export { ZipCodeValidator };

export { ZipCodeValidator as mainValidator };

重新導(dǎo)出

我們經(jīng)常會(huì)去擴(kuò)展其它模塊,并且只導(dǎo)出那個(gè)模塊的部分內(nèi)容。 重新導(dǎo)出功能并不會(huì)在當(dāng)前模塊導(dǎo)入那個(gè)模塊或定義一個(gè)新的局部變量。

ParseIntBasedZipCodeValidator.ts

export class ParseIntBasedZipCodeValidator {

? ? isAcceptable(s: string) {

? ? ? ? return s.length === 5 && parseInt(s).toString() === s;

? ? }

}

// 導(dǎo)出原先的驗(yàn)證器但做了重命名

export {ZipCodeValidator as RegExpBasedZipCodeValidator} from "./ZipCodeValidator";

或者一個(gè)模塊可以包裹多個(gè)模塊,并把他們導(dǎo)出的內(nèi)容聯(lián)合在一起通過語法:export * from "module"。

AllValidators.ts

export * from "./StringValidator"; // exports interface StringValidator

export * from "./LettersOnlyValidator"; // exports class LettersOnlyValidator

export * from "./ZipCodeValidator";? // exports class ZipCodeValidator

導(dǎo)入

模塊的導(dǎo)入操作與導(dǎo)出一樣簡單。 可以使用以下 import形式之一來導(dǎo)入其它模塊中的導(dǎo)出內(nèi)容。

導(dǎo)入一個(gè)模塊中的某個(gè)導(dǎo)出內(nèi)容

import { ZipCodeValidator } from "./ZipCodeValidator";

let myValidator = new ZipCodeValidator();

可以對導(dǎo)入內(nèi)容重命名

import { ZipCodeValidator as ZCV } from "./ZipCodeValidator";

let myValidator = new ZCV();

將整個(gè)模塊導(dǎo)入到一個(gè)變量,并通過它來訪問模塊的導(dǎo)出部分

import * as validator from "./ZipCodeValidator";

let myValidator = new validator.ZipCodeValidator();

具有副作用的導(dǎo)入模塊

盡管不推薦這么做,一些模塊會(huì)設(shè)置一些全局狀態(tài)供其它模塊使用。 這些模塊可能沒有任何的導(dǎo)出或用戶根本就不關(guān)注它的導(dǎo)出。 使用下面的方法來導(dǎo)入這類模塊:

import "./my-module.js";

默認(rèn)導(dǎo)出

每個(gè)模塊都可以有一個(gè)default導(dǎo)出。 默認(rèn)導(dǎo)出使用 default關(guān)鍵字標(biāo)記;并且一個(gè)模塊只能夠有一個(gè)default導(dǎo)出。 需要使用一種特殊的導(dǎo)入形式來導(dǎo)入 default導(dǎo)出。

default導(dǎo)出十分便利。 比如,像JQuery這樣的類庫可能有一個(gè)默認(rèn)導(dǎo)出 jQuery或$,并且我們基本上也會(huì)使用同樣的名字jQuery或$導(dǎo)出JQuery。

JQuery.d.ts

declare let $: JQuery;

export default $;

App.ts

import $ from "JQuery";

$("button.continue").html( "Next Step..." );

類和函數(shù)聲明可以直接被標(biāo)記為默認(rèn)導(dǎo)出。 標(biāo)記為默認(rèn)導(dǎo)出的類和函數(shù)的名字是可以省略的。

ZipCodeValidator.ts

export default class ZipCodeValidator {

? ? static numberRegexp = /^[0-9]+$/;

? ? isAcceptable(s: string) {

? ? ? ? return s.length === 5 && ZipCodeValidator.numberRegexp.test(s);

? ? }

}

Test.ts

import validator from "./ZipCodeValidator";

let myValidator = new validator();

或者

StaticZipCodeValidator.ts

const numberRegexp = /^[0-9]+$/;

export default function (s: string) {

? ? return s.length === 5 && numberRegexp.test(s);

}

Test.ts

import validate from "./StaticZipCodeValidator";

let strings = ["Hello", "98052", "101"];

// Use function validate

strings.forEach(s => {

? console.log(`"${s}" ${validate(s) ? " matches" : " does not match"}`);

});

default導(dǎo)出也可以是一個(gè)值

OneTwoThree.ts

export default "123";

Log.ts

import num from "./OneTwoThree";

console.log(num); // "123"

export = 和 import = require()

CommonJS和AMD的環(huán)境里都有一個(gè)exports變量,這個(gè)變量包含了一個(gè)模塊的所有導(dǎo)出內(nèi)容。

CommonJS和AMD的exports都可以被賦值為一個(gè)對象, 這種情況下其作用就類似于 es6 語法里的默認(rèn)導(dǎo)出,即 export default語法了。雖然作用相似,但是 export default 語法并不能兼容CommonJS和AMD的exports。

為了支持CommonJS和AMD的exports, TypeScript提供了export =語法。

export =語法定義一個(gè)模塊的導(dǎo)出對象。 這里的對象一詞指的是類,接口,命名空間,函數(shù)或枚舉。

若使用export =導(dǎo)出一個(gè)模塊,則必須使用TypeScript的特定語法import module = require("module")來導(dǎo)入此模塊。

ZipCodeValidator.ts

let numberRegexp = /^[0-9]+$/;

class ZipCodeValidator {

? ? isAcceptable(s: string) {

? ? ? ? return s.length === 5 && numberRegexp.test(s);

? ? }

}

export = ZipCodeValidator;

Test.ts

import zip = require("./ZipCodeValidator");

// Some samples to try

let strings = ["Hello", "98052", "101"];

// Validators to use

let validator = new zip();

// Show whether each string passed each validator

strings.forEach(s => {

? console.log(`"${ s }" - ${ validator.isAcceptable(s) ? "matches" : "does not match" }`);

});

生成模塊代碼

根據(jù)編譯時(shí)指定的模塊目標(biāo)參數(shù),編譯器會(huì)生成相應(yīng)的供Node.js (CommonJS),Require.js (AMD),UMD,SystemJS或ECMAScript 2015 native modules (ES6)模塊加載系統(tǒng)使用的代碼。 想要了解生成代碼中 define,require 和 register的意義,請參考相應(yīng)模塊加載器的文檔。

下面的例子說明了導(dǎo)入導(dǎo)出語句里使用的名字是怎么轉(zhuǎn)換為相應(yīng)的模塊加載器代碼的。

SimpleModule.ts

import m = require("mod");

export let t = m.something + 1;

AMD / RequireJS SimpleModule.js

define(["require", "exports", "./mod"], function (require, exports, mod_1) {

? ? exports.t = mod_1.something + 1;

});

CommonJS / Node SimpleModule.js

let mod_1 = require("./mod");

exports.t = mod_1.something + 1;

UMD SimpleModule.js

(function (factory) {

? ? if (typeof module === "object" && typeof module.exports === "object") {

? ? ? ? let v = factory(require, exports); if (v !== undefined) module.exports = v;

? ? }

? ? else if (typeof define === "function" && define.amd) {

? ? ? ? define(["require", "exports", "./mod"], factory);

? ? }

})(function (require, exports) {

? ? let mod_1 = require("./mod");

? ? exports.t = mod_1.something + 1;

});

System SimpleModule.js

System.register(["./mod"], function(exports_1) {

? ? let mod_1;

? ? let t;

? ? return {

? ? ? ? setters:[

? ? ? ? ? ? function (mod_1_1) {

? ? ? ? ? ? ? ? mod_1 = mod_1_1;

? ? ? ? ? ? }],

? ? ? ? execute: function() {

? ? ? ? ? ? exports_1("t", t = mod_1.something + 1);

? ? ? ? }

? ? }

});

Native ECMAScript 2015 modules SimpleModule.js

import { something } from "./mod";

export let t = something + 1;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容