【问题标题】:Why is TypeScript generating an IIFE for a namespace?为什么 TypeScript 会为命名空间生成 IIFE?
【发布时间】:2021-07-15 09:41:54
【问题描述】:

我有这个 TS 代码:

export namespace Constants
{
    export var x = 0;        
}

如果我用 'tsc' 编译它,我会得到这个 JS 代码:

"use strict";
exports.__esModule = true;
exports.Constants = void 0;

var Constants;
(function (Constants) {
    Constants.x = 0;
})(Constants = exports.Constants || (exports.Constants = {}));

我的问题是。为什么 'tsc' 将命名空间编译为 IIFE 而不是像这样简单且可读性更高的对象?

var Constants = {};
Constants.x = 0;

有什么特别的原因吗?

这里有other questions similar。除了他们没有给出任何真实的答案。这个问题的不同之处在于,命名空间只是一个用于隔离代码的简单容器,因此它必须尽可能简单易读,而 IIFE 并不是最好的解决方案。

【问题讨论】:

  • @MarioSantini 这个问题给出的生成的 ES5 代码是完美的。没有一个角色可以改变。显然,TypeScript 团队关心生成的代码。
  • @Paleo 我删除了我的评论并做出了回答,因为太长了。我希望它更有意义。

标签: javascript typescript namespaces iife


【解决方案1】:

我写了一条评论,但也许一个答案是更好地表达我的观点的正确方式。

我认为无法回答您的问题,因为这是 TypeScript 团队的选择问题。

无论如何我都会在这里写下我对这个话题的看法。

我认为他们不太关心生成的 JavaScript 代码的可读性。

他们只是关心它是否按预期工作,并且您的简单示例未优化这一事实,我想这只是他们认为不应该对其进行优化的事实。

命名空间与模块完全一样,可以包含代码、函数、类。它可能很大很复杂。

即使在像您展示的那样简单的情况下,一个普通对象也会以与函数相同的方式运行,但在 JavaScript 中,es5 在语义上并不相同。

如果你在 TypeScript 中使用普通对象,它会是,但命名空间是一个模块,JavaScrip es5 上唯一的等价物是一个函数。

我认为,如果您针对不同版本的 JavaScript(例如具有模块的版本),它可能会发生变化。

【讨论】:

    【解决方案2】:

    命名空间是一个范围。而在 JavaScript 中提供作用域的经典方法是将代码放入函数中。

    特别是,IIFE 是一种封装局部变量的方法:

    export namespace Constants
    {
      const val = 2
      export const x = val * 2;
    }
    
    // Here, 'val' must be inaccessible.
    // And we can create another 'val' variable:
    
    const val = 3; // OK
    

    使用“简单对象”实现,楼上的代码将被编译为:

    const Constants = {};
    const val = 2
    Constants.x = val * 2;
    
    // With this implementation, 'val' could be accessed outside the namespace at runtime.
    // And we couldn't create another 'val' variable:
    
    const val = 3; // Error: already defined.
    

    【讨论】:

    • 我很抱歉,但我认为你不明白这一点。我同意你的看法,«这是一种封装局部变量的方法。»关键是:为什么是 IIFE 而不是简单的对象?
    • 对不起Paleo,在回复之前仔细阅读问题。显然,你是对的«如果没有 IIFE...'val' 将在运行时在命名空间之外访问»。但在这种情况下,您的实现不在当前的竞赛范围内。
    • @AlterEgo 您需要澄清什么是“当前比赛”。
    • @AlterEgo - 在回复之前想阅读the spec 吗?第 14 页,1.10 命名空间
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-05
    • 2019-09-28
    • 2015-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多