为什么TypeScript会为类生成IIFE?

时间:2016-03-25 09:18:33

标签: javascript class typescript

查看此TypeScript代码:

textview

它围绕构造函数和所有原型函数声明生成一个IIFE(立即调用的函数表达式),如:

class Greeter {
    greet() {}
}

这里有什么优势?当我读到IIFE时,我发现定义模块有很多用处。据我所知,Typescript不会在IIFE中生成会污染全局命名空间的任何内容。

在我看来,这个类宣言没有优势:

var Greeter = (function () {
    function Greeter() {
    }
    Greeter.prototype.greet = function () { };
    return Greeter;
}());

这是什么原因?

2 个答案:

答案 0 :(得分:9)

避免全局名称空间污染。

它是一种clousure模式,其中内部函数可以访问其父元素属性。通过IIFE,返回内部函数的参考。

下面是两个场景,其中IIFE模式非常有用,原因是TypeScript Compiler生成IIFE模式的原因:

  1. 继承实现:它将BaseClass作为参数传递给IIFE。如果IIFEE不存在BaseClass将是全局变量,从而污染全局命名空间。
  2. <强>打字稿

    class Greeter extends BaseController {
        greeting: string;
        constructor(message: string) {
            this.greeting = message;
        }
        greet() {
            return "Hello, " + this.greeting;
        }
    }
    

    <强> JS

    var Greeter = (function(_super) {
        __extends(Greeter, _super);
    
        function Greeter(message) {
            this.greeting = message;
        }
        Greeter.prototype.greet = function() {
            return "Hello, " + this.greeting;
        };
        return Greeter;
    }(BaseController));
    
    1. 模块模式实现:其中app只有一个全局变量,如'app',所有其他功能都包含在app.cartapp.catalog等对象中。只有变量通过模块和其他所有变量公开功能被添加到模块本身,这只能由IIFE实现。
    2. <强>打字稿

      module App.Controller {
          export class Greeter extends BaseController {
              greeting: string;
              constructor(message: string) {
                  this.greeting = message;
              }
              greet() {
                  return "Hello, " + this.greeting;
              }
          }
      }
      

      <强> JS

      var App;
      (function (App) {
          var Controller;
          (function (Controller) {
              var Greeter = (function (_super) {
                  __extends(Greeter, _super);
                  function Greeter(message) {
                      this.greeting = message;
                  }
                  Greeter.prototype.greet = function () {
                      return "Hello, " + this.greeting;
                  };
                  return Greeter;
              }(BaseController));
              Controller.Greeter = Greeter;
          })(Controller = App.Controller || (App.Controller = {}));
      })(App || (App = {}));
      

      将此js代码复制/粘贴到浏览器控制台,只会全局创建App变量。休息功能将在App。

      谢谢, mkdudeja

答案 1 :(得分:6)

这很有趣。我认为typescript编译器通过将表达式分配给范围中的变量来编译从ClassDeclaration推导出的ClassExpression,因此他们不必独立处理这些情况。这简化了TypeScript编译器,并使生成的代码有点模块化(我想说更具可读性,但这只是一个品味问题)。

class Bar { };
foo(class Baz { });
var Baa = class Bab { };

编译成:

var Bar = (function () {
    function Bar() {
    }
    return Bar;
}());
;
foo((function () {
    function Baz() {
    }
    return Baz;
}()));
var Baa = (function () {
    function Bab() {
    }
    return Bab;
}());

请参阅,ClassDeclaration编译为分配给局部变量的ClassExpression