代码之家  ›  专栏  ›  技术社区  ›  Jorge Belano Murphy

TypeScript中类和命名空间之间的差异

  •  5
  • Jorge Belano Murphy  · 技术社区  · 7 年前

    两者的区别是什么 classes namespaces 在TypeScript中?我知道,如果您使用静态方法创建一个类,您可以访问它们,而无需实例化该类,这正是名称空间的要点之一。

    我还知道,您可以使用相同的名称创建多个名称空间,当编译为JS时,它们的方法将属于同一个函数。

    但我不知道什么时候该用这个或那个。。。对我来说,最终,类和名称空间几乎是一样的,所以我想我遗漏了一些东西。。。

    2 回复  |  直到 4 年前
        1
  •  7
  •   basarat    7 年前

    但我不知道什么时候该用这个或那个。。。对我来说,最终,类和名称空间几乎是一样的,所以我想我遗漏了一些东西。。。

    当您想要创建类的实例时,请使用类,例如。

    class Foo {
     x = 0
    }
    const foo = new Foo(); // instantiate
    

    仅当需要对类似的类/函数/变量等进行分组时才使用名称空间,例如

    namespace Foo {
      export class Bar {}
      export class Bas {}
    }
    

    重叠

    最终使用语法有重叠,例如类上的静态可以 滥用 表现得像命名空间。如果遵循此指南,则可以忽略重叠。

        2
  •  5
  •   Nikita Fedyashev    4 年前

    你说得对。名称空间和静态类是相似的。它们有一些共同的特点。它们都是ES5模式的语法糖,具有相似性- 参见 TypeScript playground

    // TypeScript
    class C {
        static readonly Name = 'C';
        static print() {
            console.log(`Name=${C.Name}`);
        }
    }
    
    namespace N {
        export const Name = 'N';
        export function print() {
            console.log(`Name=${Name}`);
        }
    }
    
    // Usage
    C.print();
    N.print();
    const c = new C();
    const n = new N(); // TS Error: Cannot use 'new' with an expression whose type lacks a call or a construct signature
    
    // Transpiled JavaScript
    var C = /** @class */ (function () {
        function C() {
        }
        C.print = function () {
            console.log("Name=" + C.Name);
        };
        C.Name = 'C';
        return C;
    }());
    
    var N;
    (function (N) {
        N.Name = 'N';
        function print() {
            console.log("Name=" + N.Name);
        }
        N.print = print;
    })(N || (N = {}));
    

    然而,它们也有自己的特点:

    • 名称空间 仅在TypeScript中,而不在ECMAScript中。他们可以被视为 IIFE 句法糖。它们可以嵌套(例如。 A.B.C )类似于C#命名空间。自ECMAScript 6以来 (ES6/ES2015) ,在大多数情况下,ES6模块比名称空间更有趣,因为在文件级处理嵌套和保持代码结构平坦更简单。

    • 类别 ES6中也提供了包含静态成员的功能。它们也是“构造函数-函数模式”的语法糖。静态类提供与命名空间相同的功能,但语法不太常见- 请参见前面的示例。

    因此,基本上,每个模式都有其与这些用例相关的哲学:

    • 对于静态(即+/-全局)成员:大多数情况下为ES6模块;TypeScript命名空间有时甚至在模块内部- 看见 TS Doc ; 或者只是一个常量对象文字,
    • 创建对象的步骤:类 (顺便说一下,也可以有静态成员,如工厂方法) ,工厂函数,仅普通对象文字。。。

    这些建议可以帮助生成更“惯用”的代码,即更易于阅读和维护。

    但您/您的团队拥有自己的代码,决定权属于您。您可以根据自己的经验尝试不同的模式来比较它们。最后,如果您选择的话,在名称空间上使用纯静态类也不错,就像使用名称空间而不是ES6模块一样。