繁体   English   中英

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

[英]Why private variable in a class is treated as public in the transpiled code

我在打字稿中添加了以下课程

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 不应访问该类(这在打字稿代码中发生)。

相同的行为应该发生在转译的 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.Since 值已经在类的构造函数中分配,它应该可以通过 p.getVariable1() 获得

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

在上面的代码中 Variable2 应该重新运行 'xyz' 但它不是。 一旦我为它赋值,它就会返回。

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

从评论中继续我们的讨论,以下是使用 public 与 private 的好处:

打字稿错误示例

IDE 会立即告诉您您正在做不应该做的事情。 如果您忽略这些错误,代码将编译为 javascript 并运行,但重点是您不要忽略这些错误。 当你写出这样糟糕的代码时,打字稿会告诉你有问题,然后你就可以解决这个问题。 如果您有一个构建过程,您可以设置它以便这些打字稿错误将使构建失败,从而迫使您在部署之前修复问题。

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

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

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

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

但是你举了一些行为非常奇怪的例子。 它们不是由于 TypeScript 转译。 我注意到你的班级 Person 有一些问题导致了他们:

  • 在 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; } get x() { return this._x; } . 这也是一个常用的 JavaScript 约定,用于指示变量是私有的,没有复杂的模式来真正拥有私有属性。

根据我的理解,在以下情况下,variable2 未定义,因为对象 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(compiled code) 对象不包含这些变量?

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM