• 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库就行。

  • 相关阅读:
    从句分析
    artDialog ( v 6.0.2 ) content 参数引入页面 html 内容
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 11 盛最多水的容器
    Java实现 LeetCode 11 盛最多水的容器
  • 原文地址:https://www.cnblogs.com/hammerc/p/6898040.html
Copyright © 2020-2023  润新知