【问题标题】:Difference between classes and namespaces in TypeScriptTypeScript 中的类和命名空间之间的区别
【发布时间】:2018-06-23 10:38:21
【问题描述】:

TypeScript 中的 classesnamespaces 到底有什么区别?我知道,如果您使用静态方法创建一个类,您可以在不实例化该类的情况下访问它们,而这正是我猜想的命名空间的要点之一。

我也知道你可以创建多个同名的命名空间,并且它们的方法在编译成 JS 时将属于同一个函数。

但我不知道什么时候使用一个或另一个......对我来说,最后,类和命名空间几乎相同,所以我想我错过了一些东西......

【问题讨论】:

  • 如果你不打算实例化一个类,就不要使用它。
  • @FelixKling 我用什么代替?那么静态方法的意义何在?

标签: javascript class typescript namespaces difference


【解决方案1】:

但我不知道什么时候使用一个或另一个......对我来说,最后,类和命名空间几乎相同,所以我想我错过了一些东西......

当你想创建它的实例时使用类,例如

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

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

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

重叠

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

【讨论】:

    【解决方案2】:

    你是对的。命名空间和静态类是相似的。他们有一些共同的特点。它们都是具有相似性的 ES5 模式的语法糖 - cf。 TypeScript playground 给出的转译 JavaScript:

    // 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 模块。

    【讨论】:

    • @jorge-belano-murphy:请您查看我的答案并给我反馈(cmets,标记有用,批准)吗?
    猜你喜欢
    • 2020-08-21
    • 2020-10-21
    • 2012-08-12
    • 2016-05-28
    • 1970-01-01
    • 2011-06-26
    • 1970-01-01
    • 2014-09-20
    • 2011-03-27
    相关资源
    最近更新 更多