轉(zhuǎn)發(fā) # TypeScript基礎(chǔ)入門(mén)之模塊(一)
模塊
關(guān)于術(shù)語(yǔ)的一點(diǎn)說(shuō)明: 請(qǐng)務(wù)必注意一點(diǎn)吊输,TypeScript 1.5里術(shù)語(yǔ)名已經(jīng)發(fā)生了變化胧华。 "內(nèi)部模塊"現(xiàn)在稱(chēng)做"命名空間"淘正。 "外部模塊"現(xiàn)在則簡(jiǎn)稱(chēng)為"模塊"爆雹,這是為了與 ECMAScript 2015里的術(shù)語(yǔ)保持一致,(也就是說(shuō) module X { 相當(dāng)于現(xiàn)在推薦的寫(xiě)法 namespace X {)勺三。
介紹
從ECMAScript 2015開(kāi)始雷滚,JavaScript引入了模塊的概念。TypeScript也沿用這個(gè)概念吗坚。
模塊在其自身的作用域里執(zhí)行祈远,而不是在全局作用域里;這意味著定義在一個(gè)模塊里的變量商源,函數(shù)车份,類(lèi)等等在模塊外部是不可見(jiàn)的,除非你明確地使用export形式之一導(dǎo)出它們牡彻。 相反扫沼,如果想使用其它模塊導(dǎo)出的變量,函數(shù),類(lèi)充甚,接口等的時(shí)候以政,你必須要導(dǎo)入它們霸褒,可以使用import形式之一伴找。
模塊是自聲明的;兩個(gè)模塊之間的關(guān)系是通過(guò)在文件級(jí)別上使用imports和exports建立的废菱。
模塊使用模塊加載器去導(dǎo)入其它的模塊技矮。 在運(yùn)行時(shí),模塊加載器的作用是在執(zhí)行此模塊代碼前去查找并執(zhí)行這個(gè)模塊的所有依賴殊轴。 大家最熟知的JavaScript模塊加載器是服務(wù)于Node.js的 CommonJS和服務(wù)于Web應(yīng)用的Require.js衰倦。
TypeScript與ECMAScript 2015一樣,任何包含頂級(jí)import或者export的文件都被當(dāng)成一個(gè)模塊旁理。相反地樊零,如果一個(gè)文件不帶有頂級(jí)的import或者export聲明,那么它的內(nèi)容被視為全局可見(jiàn)的(因此對(duì)模塊也是可見(jiàn)的)孽文。
導(dǎo)出
導(dǎo)出聲明
任何聲明(比如變量驻襟,函數(shù),類(lèi)芋哭,類(lèi)型別名或接口)都能夠通過(guò)添加export關(guān)鍵字來(lái)導(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): boolean {
return s.length === 5 && numberRegexp.test(s);
}
}
導(dǎo)出語(yǔ)句
導(dǎo)出語(yǔ)句很便利,因?yàn)槲覀兛赡苄枰獙?duì)導(dǎo)出的部分重命名减牺,所以上面的例子可以這樣改寫(xiě):
export const numberRegexp = /^[0-9]+$/;
class ZipCodeValidator implements StringValidator {
isAcceptable(s: string): boolean {
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): boolean {
return s.length === 5 && parseInt(s).toString() === s;
}
}
export { ZipCodeValidator as RegExpBaseZipCodeValidator } from './ZipCodeValidator';
或者一個(gè)模塊可以包裹多個(gè)模塊肥隆,并把他們導(dǎo)出的內(nèi)容聯(lián)合在一起通過(guò)語(yǔ)法:export * from "module"
。
AllValidators.ts
export * from "./StringValidator"; // exports interface 'StringValidator'
export * from "./ZipCodeValidator"; // exports class 'ZipCodeValidator'
導(dǎo)入
模塊的導(dǎo)入操作與導(dǎo)出一樣簡(jiǎn)單稚失。 可以使用以下import形式之一來(lái)導(dǎo)入其它模塊中的導(dǎo)出內(nèi)容栋艳。
導(dǎo)入一個(gè)模塊中的某個(gè)導(dǎo)出內(nèi)容
import { ZipCodeValidator } from "./ZipCodeValidator";
let myValidator = new ZipCodeValidator();
可以對(duì)導(dǎo)入內(nèi)容重命名
import { ZipCodeValidator as ZCV } from "./ZipCodeValidator";
let myValidator = new ZCV();
將整個(gè)模塊導(dǎo)入到一個(gè)變量,并通過(guò)它來(lái)訪問(wèn)模塊的導(dǎo)出部分
import * as validator from "./ZipCodeValidator";
let myValidator = new validator.ZipCodeValidator();
具有副作用的導(dǎo)入模塊
盡管不推薦這么做墩虹,一些模塊會(huì)設(shè)置一些全局狀態(tài)供其它模塊使用嘱巾。 這些模塊可能沒(méi)有任何的導(dǎo)出或用戶根本就不關(guān)注它的導(dǎo)出。 使用下面的方法來(lái)導(dǎo)入這類(lèi)模塊:
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)入形式來(lái)導(dǎo)入 default導(dǎo)出菌湃。
default導(dǎo)出十分便利问拘。 比如,像JQuery這樣的類(lèi)庫(kù)可能有一個(gè)默認(rèn)導(dǎo)出 jQuery或導(dǎo)出JQuery骤坐。
JQuery.d.ts
declare let $: JQuery;
export default $;
App.ts
import $ from "JQuery";
$("button.continue").html( "Next Step..." );
類(lèi)和函數(shù)聲明可以直接被標(biāo)記為默認(rèn)導(dǎo)出绪杏。 標(biāo)記為默認(rèn)導(dǎo)出的類(lèi)和函數(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都有一個(gè)exports對(duì)象的概念纽绍,它包含了一個(gè)模塊的所有導(dǎo)出內(nèi)容蕾久。
它們也支持把exports替換為一個(gè)自定義對(duì)象。 默認(rèn)導(dǎo)出就好比這樣一個(gè)功能拌夏;然而僧著,它們卻并不相互兼容。 TypeScript模塊支持 export =語(yǔ)法以支持傳統(tǒng)的CommonJS和AMD的工作流模型障簿。
export =
語(yǔ)法定義一個(gè)模塊的導(dǎo)出對(duì)象盹愚。 它可以是類(lèi),接口站故,命名空間皆怕,函數(shù)或枚舉。
若要導(dǎo)入一個(gè)使用了export =的模塊時(shí)西篓,必須使用TypeScript提供的特定語(yǔ)法import module = require("module")
愈腾。
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");
// 嘗試一些字符
let strings = ["Hello", "98052", "101"];
// 使用validator
let validator = new zip();
// 檢測(cè)每個(gè)字符串,是否通過(guò)驗(yàn)證
strings.forEach(s => {
console.log(`"${ s }" - ${ validator.isAcceptable(s) ? "matches" : "does not match" }`);
});