Javascript 为什么TypeScript会在生命中打包一个类?

Javascript 为什么TypeScript会在生命中打包一个类?,javascript,typescript,ecmascript-5,iife,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 "

下面是一个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;
}());
但是,当它作为构造函数呈现时,它通常以相同的方式工作。当然,这看起来更像Java脚本和手写体:)

用法:

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

Greater.what();  // -> "Greater"
var greater = new Greater("World!");
greater.greet(); // -> "Hello, World!
在生活中包装它的好处或动机是什么

我做了一个天真的基准:

console.time("Greeter");
for(let i = 0; i < 100000000; i++) {
    new Greeter("world" + i);
}
console.timeEnd("Greeter");
console.time(“问候者”);
对于(设i=0;i<100000000;i++){
新迎宾员(“世界”+i);
}
控制台。时间结束(“接线员”);
它显示了几乎相同的实例化速度。当然,我们不能期望有任何不同,因为生命只有一次解决


我在想也许是因为结束了,但生活不需要争论。它不能是一个闭包。

这样做是为了在这样的边缘情况下保留本机类行为,即在定义类之前,有人试图使用类
Greeter

// this is javascript code, not TypeScript

console.log(Greeter.What());

class Greeter {
}

Greeter.What = function What() {
    return "Greater";
}
对于本机类实现,应该打印
ReferenceError:Greeter未定义

在IIFE中传输和包装时,结果非常接近:
TypeError:无法读取未定义的属性“What”

在没有IIFE的情况下,未包装的函数是,并且名称
Greeter
在定义之前在范围内,因此会产生不同的错误:
TypeError:Greeter。什么不是函数


请注意,IIFE不用于隐藏私有实例或类属性,因为它无论如何都不是必需的。传输时,实例属性被指定为构造函数内部的
的属性,静态属性被指定为
Greeter
对象的属性-不创建任何变量。

TypeScript将在类之间存在继承的情况下向IIFE传递参数。例如,当
Greeter
扩展
BaseGreeter
类时,使用下面的闭包:

var Greeter = /** @class */ (function (_super) {
    // __extends is added by the TS transpiler to simulate inheritance
    __extends(Greeter, _super);
    function Greeter(subject) {
        var _this = _super.call(this) || this;
        _this.subject = subject;
        return _this;
    }
    Greeter.What = function () {
        return "Greater";
    };
    Greeter.prototype.greet = function () {
        return "Hello, " + this.subject;
    };
    return Greeter;
}(BaseGreeter));

var
不会被提升是的,另一个答案是正确的-您必须能够引入一个名称来引用基类,因为例如基类可能是一个。iLife是安全引入一个不会与外部范围内的任何内容冲突的名称的唯一方法。我认为两个答案对于不同的事情都是正确的。是的,
var
没有被提升,但是
函数迎宾器本身(如OP所示)会被提升,我认为这是artem的观点。另外,请注意TS实际上并没有将其用于私有字段。@charlietfl TS,实际上。在JS中,它们都是公开的。
var Greeter = /** @class */ (function (_super) {
    // __extends is added by the TS transpiler to simulate inheritance
    __extends(Greeter, _super);
    function Greeter(subject) {
        var _this = _super.call(this) || this;
        _this.subject = subject;
        return _this;
    }
    Greeter.What = function () {
        return "Greater";
    };
    Greeter.prototype.greet = function () {
        return "Hello, " + this.subject;
    };
    return Greeter;
}(BaseGreeter));