JavaScript如果要替名稱加上命名空間,不外乎就是利用物件或是模組來達成。但在TypeScript中,有namespace
關鍵字可以讓我們快速地新增命名空間來用。
namespace
關鍵字的用法很簡單,如下:
namespace 命名空間的名稱(可以用句號連接多個名稱) { 程式敘述區塊 }
若要將namespace
程式區塊中的名稱暴露出來,與模組一樣,是在var
、let
、const
、function
、class
、interface
、enum
、type
關鍵字前加上export
關鍵字。當然,namespace
程式區塊中也還可以再使用namespace
關鍵字來建立程式敘述區塊,且namespace
關鍵字前也是可以加上export
關鍵字來將其暴露的。
例如:
namespace org.magiclen {
export namespace A {
export function f() {
console.log("A");
}
}
export namespace B {
export function f() {
console.log("B");
}
}
export namespace AB {
export function f() {
A.f();
B.f();
}
}
}
org.magiclen.A.f();
org.magiclen.B.f();
org.magiclen.AB.f();
以上程式的輸出結果如下:
B
A
B
擴充命名空間
我們可以建立出相同名稱的namespace
程式敘述區塊,替已存在的命名空間擴充原本不存在的名稱。
例如:
namespace org.magiclen {
export namespace A {
export function f() {
console.log("A");
}
}
export namespace A {
export function f2() {
console.log("A");
}
}
export namespace B {
export function f() {
console.log("B");
}
}
export namespace AB {
export function f() {
A.f();
B.f();
}
}
}
namespace org.magiclen.A {
export function ff() {
console.log("AA");
}
}
namespace org.magiclen {
export function f() {
console.log("Hello!");
}
}
org.magiclen.A.f();
org.magiclen.B.f();
org.magiclen.AB.f();
org.magiclen.A.ff();
org.magiclen.f();
命名空間除了可以拿來擴充同名的命名空間之外,也可以拿來擴充同名的變數、常數、函數、類別、介面、列舉和型別別名下的名稱。有點詭異,但十分方便。例如:
type T = number | string;
namespace T {
export const n = 1;
}
console.log(T.n);
function f() {
}
namespace f {
export const s = "2";
}
console.log(f.s);
命名空間的網頁應用
實際編譯以下TypeScript程式:
namespace A {
export function f() {
console.log("A");
}
}
會得到這樣的JavaScript程式:
var A;
(function (A) {
function f() {
console.log('A');
}
A.f = f;
})(A || (A = {}));
A
命名空間實際上在JavaScript中會是一個變數A
。也就是說,利用這樣的性質,我們可以很容易地在網頁瀏覽器上透過命名空間產生的變數,來存取這個變數下的名稱。
舉例來說,現在有以下兩個檔案:
namespace A {
export function f() {
console.log("A");
}
}
namespace B {
export function f() {
console.log("B");
}
}
以上兩個檔案雖然都不是TypeScript模組(因為最外層並沒有使用export
關鍵字),但是它們的f
函數在網頁中並不會有衝突,可以透過全域變數A
和B
來呼叫它們。如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script src="a.js"></script>
<script src="b.js"></script>
</head>
<body>
<script>
A.f();
B.f();
</script>
</body>
</html>
總結
至此我們已經把TypeScript能夠宣告的名稱類型(變數、常數、函數、類別、介面、列舉、型別別名、模組、命名空間)都學全了。只是有些名稱可以當作型別,有些名稱可以當作值,有些名稱又可以當作命名空間來用,實在很混亂。在此用以下表格做個歸納:
名稱類型 | 命名空間 | 型別 | 值 | 例子 |
---|---|---|---|---|
var |
否 | 否 | 是 |
var name = "MagicLen";
console.log(name);
|
let |
否 | 否 | 是 |
let name = "MagicLen";
console.log(name);
|
const |
否 | 否 | 是 |
const name = "MagicLen";
console.log(name);
|
function |
否 | 否 | 是 |
function f() {}
console.log(f);
|
class |
否 | 是 | 是 |
class C {}
console.log(C);
let o: C = new C();
|
interface |
否 | 是 | 否 |
interface I {}
class C implements I {}
let o: I = new C();
|
enum |
否 | 是 | 是 |
enum E { // it can not be a const enum
V
}
console.log(E);
let o: E = E.V;
|
type |
否 | 是 | 否 |
interface I {}
let o: I;
|
import |
否 | 否 | 是 |
import * as fs from "node:fs";
console.log(fs);
|
namespace |
是 | 否 | 否 |
namespace NS {
export function f() {}
}
NS.f();
|
在下一個章節中,我們要來學習TypeScript的裝飾器(Decorator)。
下一章:裝飾器(Decorator)。