为什么TypeScript在IIFE中打包一个类?

时间:2019-05-11 01:05:36

标签: javascript typescript ecmascript-5 iife

这是TypeScript类:

class Greeter {
    public static what(): string {
        return "Greater";
    }

    public subject: string;

    constructor(subject: string) {
        this.subject = subject;
    }

    public greet(): string {
        return "Hello, " + this.subject;
    }
}

当TS瞄准ES5时,它将被移植到IIFE:

var Greeter = /** @class */ (function () {
    function Greeter(subject) {
        this.subject = subject;
    }
    Greeter.what = function () {
        return "Greater";
    };
    Greeter.prototype.greet = function () {
        return "Hello, " + this.subject;
    };
    return Greeter;
}());

但是,当它作为构造函数呈现时,它通常以相同的方式工作。当然,它看起来更像JavaScript和手写的:)

function Greeter(subject) {
    this.subject = subject;
}
Greeter.what = function () {
    return "Greater";
};
Greeter.prototype.greet = function () {
    return "Hello, " + this.subject;
};

用法:

两个代码块的工作方式相同:

Greater.what();  // -> "Greater"
var greater = new Greater("World!");
greater.greet(); // -> "Hello, World!

将其包装在IIFE中有什么好处或动机?

我做了一个幼稚的基准测试

console.time("Greeter");
for(let i = 0; i < 100000000; i++) {
    new Greeter("world" + i);
}
console.timeEnd("Greeter");

它显示出几乎相同的实例化速度。当然,我们不能指望有任何区别,因为IIFE仅解决了一次。

我当时在想,也许是因为关闭,但是IIFE并没有争论。不能是闭包。

2 个答案:

答案 0 :(得分:11)

在类之间存在继承的情况下,TypeScript将参数传递给IIFE。例如,当library("imputeTS") na.interpolation(yourDataWithNAs) 扩展Greeter类时,将使用下面的闭包:

BaseGreeter

答案 1 :(得分:10)

这样做是为了在这样的极端情况下保留本机类的行为,在这种情况下,有人试图在定义类Greeter之前使用它:

// this is javascript code, not TypeScript

console.log(Greeter.What());

class Greeter {
}

Greeter.What = function What() {
    return "Greater";
}

使用本机类实现时,应打印ReferenceError: Greeter is not defined

在IIFE中转堆和包装后,结果非常接近:TypeError: Cannot read property 'What' of undefined

在没有IIFE的情况下,展开函数为hoisted,名称Greeter在定义之前就在作用域内,因此会产生不同的错误:TypeError: Greeter.What is not a function

请注意,IIFE并不用于隐藏私有实例或类属性,因为无论如何都不需要。编译后,实例属性被分配为构造函数内this的属性,而静态属性被分配为Greeter对象的属性-不创建任何变量。