为什么类中的私有变量在转换后的代码中被视为公共变量

时间:2017-09-24 15:19:50

标签: javascript typescript ecmascript-5 typescript2.0 tsc

我在typescript中添加了以下类

class Person {
    private variable1;
    public varibele2;

    Person(){
        this.variable1 = 'abc';
        this.varibele2 = 'xyz'; 
    }

    public getVariable1(){
        return this.variable1;        
    }
}

所以当我使用tsc编译代码时,它会生成以下代码

var Person =  (function () {
    function Person() {
    }
    Person.prototype.Person = function () {
        this.variable1 = 'abc';
        this.varibele2 = 'xyz';
    };
    Person.prototype.getVariable1 = function () {
        return this.variable1;
    };
    return Person;
}());

由于variable1是私有的,因此该类的obj无法访问(在typescript代码中发生)。

同样的行为应该发生在已编译的es5代码中(但不会发生)。

在上面示例的已编译代码中,我创建了Person的对象

var p = new Person();
console.log(p.variable1); // undefined 
p.variable1 = 'abc1';  // setting value to variable 1 
console.log(p.variable1); // 'abc1'
console.log(p.getVariable1()); // 'abc1'

在上面的代码中,我不能设置或获取variable1的值。

var p = new Person();
console.log(p.getVariable1()); // 'undefined' 
p.variable1 = 'abc1';  // setting value to variable1 
console.log(p.getVariable1()); // 'abc1'

在上面的代码中,我尝试使用p.getVariable1()获取值,并且我得到undefined。因为值已经在类的构造函数中分配,所以它应该可以通过p.getVariable1()

获得
var p = new Person();
console.log(p.variable2); // undefined
p.variable2 = 'xyz1'; // setting value
console.log(p.variable2);// 'xyz1'

在上面的代码中,Variable2应该重新启动' xyz'但事实并非如此。一旦我为它赋值,它就会返回。

因此私有和公共变量的行为在转换代码中是相同的,并且非常令人困惑。 它不返回在构造函数中赋值的值。

4 个答案:

答案 0 :(得分:2)

要继续我们对评论的讨论,以下是使用公共与私有的好处:

example of typescript errors

IDE会立即告诉您,您正在做一些您不应该做的事情。如果您忽略这些错误,代码将编译为javascript并运行,但关键是您忽略这些错误。当您编写这样的错误代码时,typescript会告诉您存在问题,然后您可以解决问题。如果您有构建过程,则可以对其进行设置,以便这些打字错误将使构建失败,从而迫使您在部署之前解决问题。

Typescript是一个工具,通过更早,更容易地捕获错误,帮助您编写更好的JavaScript代码。它不是改变javascript工作方式的工具。 Typescript不提供运行时类型检查,如果这就是你所追求的,你就找不到它。如果你需要闭包来隐藏变量,那么自己创建一个闭包。

答案 1 :(得分:1)

首先,回答你的主要问题:

  

为什么类中的私有变量在转换后的代码中被视为公共。

private属性以及readonly属性确实被转换为普通属性,因此是“公共”属性。我认为这是为了简化和增强转换TS→JS并支持在任何地方使用TypeScript,在对这些属性执行无效操作时会发出警告或错误:访问类外的私有属性,重新分配只读属性... < / p>

但是你给出的例子有非常奇怪的行为。它们不是由于TypeScript转换。我注意到你的班级人员遇到了一些问题:

  • 在ES6和TypeScript中,类构造函数是使用关键字constructor定义的,而不是类名。它更令人困惑,因为构造函数被转换为一个名为类的函数构造函数,这里是Person
  • 第二个属性有一个拼写错误:varibele2而不是variable2。这就是console.log(p.variable2)无法打印预期值的原因。

修复这些问题,代码的行为更具逻辑性。

class Person {
    constructor(private _variable1 = 'abc', public variable2 = 'xyz') { }

    public get variable1() { return this._variable1; }
}

console.log(new Person()); // → Person { v1: [Getter], v2: "xyz", _v1: "abc", __proto__... }

通过TypeScript playground可以获得已编译的代码。

注意:我赞成另一种语法:

  • 属性直接在构造函数中声明:它更紧凑,它启用了类型推断,我们可以指定其他初始值。
  • 私有变量名为_x,以便于编写getter get x() { return this._x; }。它也是一种常用的JavaScript约定,表明该变量是私有的,没有复杂的模式来真正拥有私有属性。

答案 2 :(得分:0)

根据我的理解,在以下情况中,变量2未定义,因为对象p不包含该变量。

在下面的代码中,我们使用p.variable2 ='xyz1'将变量包含到对象p中。所以在第三行我们得到该变量的值。

var p = new Person();
console.log(p.variable2); // undefined
p.variable2 = 'xyz1'; // setting value
console.log(p.variable2);// 'xyz1'

还有问题是,因为typescript已经声明了变量,那么为什么javascript(编译代码)对象不包含那些变量?

答案 3 :(得分:0)

如果转译的代码没有使用闭包将其设为私有,这意味着我可以在将其用作javascript库时摆弄变量,因为我永远不会知道私有是什么。因此,答案是转换打字稿的方式是不正确的,并且不是真正使用javascript的精神。