使用 TypeScript 编译类的观察

ser*_*0ne 2 javascript compiler-construction class access-modifiers typescript

在我继续之前,我想指出我已经问了一些关于 TypeScript、它的编译器以及它在其生命周期中已经实现和没有实现的问题以及 1.0 版的路线图

这个问题与TypeScript中publicprivate关键字的使用有关,以及它们与编译后的 JavaScript 有何关系。

考虑以下 TypeScript 类:

class Example {
    private messageA: string;
    public messageB: string;

    constructor(message?: string) {
        this.messageA = "private: " + message;
        this.messageB = "public: " + message;
    }

    public showMessageA(): void {
        alert(this.messageA);
    }

    private showMessageB(): void {
        alert(this.messageB);
    }
}

var example = new Example("Hello World");
Run Code Online (Sandbox Code Playgroud)

现在,当我输入example. 智能感知 ( TypeScript ) 告诉我我可以访问messageB, 和showMessageA,因为它们都是public. 然而,这种行为(虽然可能)在编译的 JavaScript 中并不明显。

这是我班级的 JavaScript 编译:

var Example = (function () {
    function Example(message) {
        this.messageA = "private: " + message;
        this.messageB = "public: " + message;
    }
    Example.prototype.showMessageA = function () {
        alert(this.messageA);
    };

    Example.prototype.showMessageB = function () {
        alert(this.messageB);
    };
    return Example;
})();

var example = new Example("Hello World");
Run Code Online (Sandbox Code Playgroud)

现在,如果我将此示例粘贴到我的浏览器控制台(我使用的是 Chrome),我可以访问messageA, messageB, showMessageAshowMessageB这意味着在 JavaScript 中,所有访问修饰符都将被忽略。

个人认为这是错误的!JavaScript 能够对访问修饰符进行建模,因此我认为 TypeScript 应该效仿。

考虑以下手写 JavaScript,它对privatepublic变量和函数进行了正确建模:

var Example = (function() {
    return function Example(message) {
        var messageA = "private: " + message;
        this.messageB = "public: " + message;

        this.showMessageA = function() {
            alert(messageA);
        }

        var showMessageB = function() {
            alert(this.messageB);
        }
    }
})();

var example = new Example("Hello World");
Run Code Online (Sandbox Code Playgroud)

现在,如果我将此示例粘贴到我的浏览器控制台中,我只能访问messageBand showMessageA,根据我尝试使用 TypeScript 实现的目标是正确的。

问题

  1. 为什么 TypeScript 编译器在编译为 JavaScript 时会忽略访问修饰符?
  2. 为什么 TypeScript 将所有方法绑定到原型,而不是基于每个实例?
  3. 如果与我的自定义实现相比,TypeScript 编译类的方式有什么好处,那是什么,为什么?

sbk*_*ing 5

使用闭包来模仿私有访问的问题是每个实例都需要每个方法的自己的副本。这意味着每次创建实例时,都必须编译每个方法函数,并且必须为新函数保留内存空间。这并不理想,也不是 TypeScript 试图实现的目标。

  • 编译的、基于类的语言和解释的、基于原型的语言之间有很大的区别。在 JavaScript 中,我们通过在原型对象上存储方法来节省内存,所有具有该原型的对象在内存中调用相同的函数,只是使用不同的上下文。使用闭包来模仿隐私意味着您没有利用原型,并且每个对象都有自己的每个方法的副本。基于类的语言不使用原型,也没有 JavaScript 的上下文概念,因此很难进行类比。 (3认同)