当前位置: 首页 > news >正文

阮一峰《TypeScript 教程》学习笔记——namespace

1. 一段话总结

TypeScript 的 namespace(命名空间) 是 ES 模块诞生前用于组织相关代码的容器化方案,核心通过 namespace 关键字包裹代码,内部成员需加 export 才能对外暴露(否则仅内部可见);支持嵌套、为外部成员起别名(用内部 import 命令),且 同名 namespace 会自动合并,还可与同名函数、class、enum 合并(需先声明函数/class/enum,确保先创建基础对象);编译后会转为 JavaScript 对象(非纯类型代码,保留运行时值);因 ES 模块是 JavaScript 标准语法、无需编译转换且更简洁,官方 不推荐使用 namespace,建议优先用 ES 模块替代。


2. 思维导图

在这里插入图片描述


3. 详细总结

一、namespace 概述

  • 定义:TypeScript 早期设计的代码组织方案,用于将相关变量、函数、类型(接口、class)封装在一个容器中,避免全局作用域污染,中文译为“命名空间”。
  • 核心定位:ES 模块诞生前的过渡方案,目前因 ES 模块成为 JavaScript 标准,官方已不推荐使用。
  • 编译特性:会转为 JavaScript 对象(非纯类型代码),保留运行时值,如:
    // TS 代码
    namespace Utility { export function log(msg:string) { console.log(msg); } }
    // 编译后 JS 代码
    var Utility;
    (function (Utility) {function log(msg) { console.log(msg); }Utility.log = log;
    })(Utility || (Utility = {}));
    

二、namespace 基本用法

1. 定义与成员暴露

  • 语法结构:用 namespace 名称 {} 包裹代码,内部成员需加 export 关键字才能对外暴露,未加 export 的成员仅内部可见。
  • 示例
    namespace Utils {// 未暴露:仅内部可用function isNumber(value:any) { return typeof value === 'number'; }// 暴露:外部可访问export function isString(value:any) { return typeof value === 'string'; }
    }
    Utils.isString('yes'); // 正确
    Utils.isNumber(123); // 报错(未暴露)
    

2. 内部引用外部成员(别名)

  • 作用:当外部成员名称较长时,用 import 别名 = 外部成员 简化引用。
  • 适用场景:内部引用其他 namespace 的暴露成员,或外部引用嵌套 namespace。
  • 示例
    // 场景1:内部引用外部 namespace 成员
    namespace App {import isStr = Utils.isString; // 别名isStr('hello'); // 等同于 Utils.isString('hello')
    }
    // 场景2:外部引用嵌套 namespace
    namespace Shapes {export namespace Polygons { export class Square {} }
    }
    import polygons = Shapes.Polygons;
    let sq = new polygons.Square(); // 简化 Shapes.Polygons.Square()
    

3. 嵌套命名空间

  • 语法:namespace 内部可嵌套另一个 namespace,嵌套的 namespace 需加 export 才能对外暴露。
  • 引用规则:必须从最外层 namespace 开始逐层引用,不能跳过外层直接访问内层。
  • 示例
    namespace Utils {export namespace Messaging { // 加 export 暴露嵌套命名空间export function log(msg:string) { console.log(msg); }}
    }
    Utils.Messaging.log('hi'); // 正确(从外层开始引用)
    Messaging.log('hi'); // 报错(跳过外层)
    

三、namespace 的输出与导入

当 namespace 定义在单独文件中时,需通过 export 输出,并在外部文件用 import 导入:

操作类型语法示例说明
文件内输出// shapes.ts
export namespace Shapes {
export class Triangle {}
}
export 对外输出整个 namespace
外部导入(写法1)import { Shapes } from './shapes';
let t = new Shapes.Triangle();
直接导入命名空间
外部导入(写法2)import * as shapes from './shapes';
let t = new shapes.Shapes.Triangle();
用别名导入整个文件,再访问命名空间

官方建议:此场景更适合用 ES 模块直接输出 class,而非嵌套 namespace(见下文对比)。

四、namespace 的合并

多个同名 namespace 或 namespace 与其他结构(函数、class、enum)会自动合并,是 namespace 的核心特性之一:

1. 合并类型及规则

合并对象合并条件示例代码注意事项
同名 namespace无额外条件,自动合并namespace A { export class X {} }
namespace A { export interface Y {} }
// 合并后:A 包含 X 和 Y
export 成员仅在原 namespace 内可用,不共享
namespace + 函数先声明函数,再定义 namespacefunction f() { return f.version; }
namespace f { export const version = '1.0'; }
f(); // '1.0'
命名空间为函数对象添加属性
namespace + class先声明 class,再定义 namespaceclass C { foo = 1; }
namespace C { export const bar = 2; }
C.bar; // 2
命名空间为类添加静态属性
namespace + enum先声明 enum,再定义 namespaceenum E { A, B }
namespace E { export function log() { console.log(E.A); } }
E.log(); // 0
enum 成员与 namespace 暴露成员不可同名,否则报错

2. 合并核心规则

  • export 成员仅在其定义的 namespace 内可用,合并后不共享;
  • 与函数、class、enum 合并时,需先声明基础结构(函数/class/enum),确保先创建对象,再通过 namespace 添加属性/方法;
  • enum 与 namespace 合并时,成员名称必须唯一,否则触发编译错误。

五、namespace 与 ES 模块的对比

因 ES 模块是 JavaScript 官方标准,namespace 已被替代,核心差异如下:

对比维度namespaceES 模块
文件内数量1个文件可定义多个 namespace1个文件对应1个模块(含 import/export 即为模块)
编译产物转为 JavaScript 对象(保留运行值,非标准语法)保留 ES 模块标准语法(import/export),无需额外转换
语法标准TypeScript 私有语法,兼容性受限JavaScript 官方标准,浏览器/Node.js 原生支持
代码简洁性嵌套引用繁琐(如 A.B.C直接输出/导入成员(如 import { X } from './a'

官方推荐方案:用 ES 模块替代 namespace,示例:

// shapes.ts(ES 模块)
export class Triangle {}
export class Square {}
// 外部使用
import * as shapes from './shapes';
let t = new shapes.Triangle();

六、官方建议

  • 优先使用 ES 模块:因 ES 模块是标准语法、无需编译转换、兼容性更好,仅在维护旧的 TypeScript 代码时使用 namespace;
  • 避免过度嵌套:namespace 嵌套会导致引用繁琐,ES 模块可通过文件目录组织代码,更清晰。

4. 关键问题

问题1:TypeScript 中 namespace 与 ES 模块的核心差异是什么?为何官方推荐用 ES 模块替代 namespace?

答案
两者核心差异体现在语法标准、编译产物、使用灵活性三方面:

  1. 语法标准:namespace 是 TypeScript 私有语法,ES 模块是 JavaScript 官方标准,浏览器/Node.js 原生支持,无需额外适配;
  2. 编译产物:namespace 编译后转为 JavaScript 对象(非标准语法,保留运行值),ES 模块保留标准 import/export 语法,无冗余转换;
  3. 使用灵活性:1个文件可定义多个 namespace,嵌套引用繁琐(如 A.B.C);ES 模块1个文件对应1个模块,可通过文件目录组织代码,直接导入所需成员(如 import { X } from './a')。

官方推荐 ES 模块的核心原因是:ES 模块符合 JavaScript 语言发展方向,兼容性更广、代码更简洁,且能完全覆盖 namespace 的代码组织需求,无需依赖 TS 私有语法。

问题2:namespace 支持与哪些结构合并?合并时有哪些必须遵守的关键规则?

答案
namespace 支持与 同名 namespace、函数、class、enum 四类结构合并,关键规则如下:

  1. 同名 namespace 合并

    • 规则:自动合并,无需额外条件;非 export 成员仅在原 namespace 内可用,不共享;
    • 示例:namespace A { export class X {} }namespace A { export interface Y {} } 合并后,A 同时包含 XY
  2. 与函数/class/enum 合并

    • 核心规则:必须先声明函数/class/enum,再定义同名 namespace(确保先创建基础对象,namespace 为其添加属性/方法);
    • 细分规则:
      • 与函数合并:namespace 为函数对象添加属性(如 function f() {} + namespace f { export const v = 1 },可通过 f.v 访问);
      • 与 class 合并:namespace 为类添加静态属性(如 class C {} + namespace C { export const v = 1 },可通过 C.v 访问);
      • 与 enum 合并:namespace 为 enum 添加方法,但 enum 成员与 namespace 暴露成员不可同名(否则报错)。

问题3:如何在 namespace 内部暴露成员供外部使用?如何在 namespace 内部引用外部成员?请结合示例说明。

答案

(1)内部成员对外暴露:用 export 关键字
  • 规则:namespace 内部成员需加 export 才能对外可见,未加 export 的成员仅内部可用;
  • 示例:
    namespace MathUtils {// 未暴露:仅内部可用function formatNum(n:number) { return n.toFixed(2); }// 暴露:外部可访问export function add(a:number, b:number) {return formatNum(a + b); // 内部可调用未暴露成员}
    }
    MathUtils.add(1.234, 5.678); // 6.91(正确,暴露成员)
    MathUtils.formatNum(1.234); // 报错(未暴露成员)
    

(2)内部引用外部成员:用 import 别名 = 外部成员 语法

  • 作用:简化外部成员的长名称引用,仅在当前 namespace 内生效;
  • 示例:
    // 外部 namespace
    namespace ExternalUtils {export function calculateArea(r:number) { return Math.PI * r ** 2; }
    }// 内部引用
    namespace App {// 为 ExternalUtils.calculateArea 起别名 areaCalcimport areaCalc = ExternalUtils.calculateArea;// 用别名调用外部成员const circleArea = areaCalc(5); // 78.5398...
    }
    
http://www.dtcms.com/a/528958.html

相关文章:

  • WEB前端技术基础(第三章:css-网页美化的衣装-上)
  • 大学生网站开发项目计划书范文南宁营销型网站设计
  • C++ 游戏开发示例:简单的贪吃蛇游戏
  • 东莞小学网站建设培训学校网站建设要点
  • 网络安全编程——TCP客户端以及服务端Python实现
  • 基于多尺度特征融合的自注意力度量学习的小样本故障诊断
  • UVa 1227 The Longest Constant Gene
  • datasophon1.2.1 二开
  • 建大网站首页华为商城网站建设
  • 运放的虚短和虚断
  • 建设网站公司兴田德润在哪里谷歌seo外链
  • 是“浴盆曲线”失灵,还是HDD变好了?
  • Tuesday JS,一款可视化小说编辑器
  • 景区旅游网站平台建设方案销售案例网站
  • 【小白笔记】input() 和 print() 这两个函数
  • 营销型网站哪家做的好东莞app
  • 部署PHP8.4(KylinV10SP3、Ubuntu2204、Rocky9.3)
  • 一套配置 双重体验:孪易 IOC 化解 端/流双渲染应用难题
  • jQuery Mobile 实例
  • 免费行情软件网站mnw做教育网站
  • WordPress网站hym地图凯里做网站
  • 东莞做网站优化哪家好网站识别手机电脑代码
  • Java---String类
  • Flame 中使用 GameWidget(完整使用手册)
  • html5制作手机网站做淘宝代码的网站
  • P2216 [HAOI2007] 理想的正方形
  • 设计模式23种-C++实现
  • 涌现的架构:集体智能框架构建解析
  • 大模型技术的核心之“效率高”
  • 分类网站怎么做seo什么网站出项目找人做