【问题标题】:typescript readonly property of class类的打字稿只读属性
【发布时间】:2016-03-23 15:16:51
【问题描述】:

我注意到 typescript 2.0 将支持只读类属性,但它尚不可用。写这篇文章的原因是,我想知道我今天如何编写代码,以便以后可以以最小的痛苦进行转换。

我想以这种方式使用具有只读属性的类:

let widget = new Widget(110, 220); // width, height
//...
widget.width(200); // to modify the width, I use a setter with validation
widget.width = 300; // note: I want this to be a compile time error
//...
let w = widget.width; // and later I want to get/draw the current width

...但是由于 fn 和属性具有相同的名称,我无法使其工作 - 所以我将 fn 名称切换为 setWidth。我宁愿不要在我所有的只读属性前加上 _ 因为在过去我发现痛苦不仅仅是键入额外字符的麻烦。而且由于 TS 的类型检查,我不需要该属性是只读(或私有)的视觉提醒。

Q1:如果 width 是如下小部件类的只读属性,上述内容是否适用于 typescript 2?

export class widget {
    readonly width:number;  // doesn't work in TS 1.8

    setWidth(w:number) {
        this.width = w;
    }
}

在短期内,我可以将属性公开,以便我可以直接访问,但我可能会直接设置属性 - 或者我可以拥有私有属性并编写 getter 和 setter。

Q2:如果我做后者,getter 比直接属性引用慢多少?我的一些属性在拖动时会被非常频繁地调用,所以速度很重要。

widget.getWidth();
// vs
widget.width;

更新

我最近找到了this posted answer,并意识到 TS 已经支持我尝试做的大部分事情:

export class Widget {
    private _width:number;
    set width(w) {if (w >= 0) this._width = w}
    get width() {return this._width}
}

使用语法与没有访问器的公共属性相同,非常漂亮:

let widget = new Widget(...);
let existingWidth = widget.width;
widget.width = newWidth;

我希望 TS2 的 readonly 限定符能让我直接读取(私有)属性(而不是通过访问器函数,这样更快),并且我的任何使用代码都不需要更改。有人知道吗?

【问题讨论】:

  • 属性访问器可以慢 20 倍,并且性能非常依赖于浏览器。请参阅以下 jsPerf - jsperf.com/data-vs-accessor-vs-getter-setter/2
  • 我运行了 jsperf(它的最新版本),操作/秒数似乎高得不切实际。它告诉我,我机器上的 Firefox 在不到 1 纳秒的时间内运行了 getter 函数。似乎不可能......除非它自动将工作分散到我的 Mac 的 4 个内核上 - 在这种情况下,它大约是 4-5 纳秒,这似乎仍然不切实际。
  • 好吧,编写自己的测试很容易。与使用属性 getter 相比,访问数据值 100,000 次需要多长时间?
  • @bnieland 这样的测试也很容易出错,请注意。
  • @bedouger,你能解释一下吗? “我希望 TS2 的 readonly 限定符能让我直接读取(私有)属性(而不是通过访问器函数,这样更快),并且我的任何使用代码都不需要更改。”

标签: typescript


【解决方案1】:

现在我正在使用 TS2,我发现 readonly 不是我想要的,因为只读限制甚至适用于类内部。所以我能想到的最好的方法是使用 private 修饰符并编写一个显式的 getter 方法。这很不幸有两个原因:读取速度(推测),以及 getter 方法名称必须不同于私有变量的名称。

【讨论】:

  • 似乎没有办法在构造函数之外初始化只读值。 C# 有 myThing = new Thing(){param=val,param2=val2} 但我认为 typescript 还没有。
  • 除非您有具体的担忧理由,否则我不会担心访问速度。至于命名,只需对 getter 使用“property_name”,对私有变量使用“_property_name”。私人成员的前下划线是大多数语言中公认的惯例。
  • 仅在 setter 中 //@ts-ignore 怎么样,我知道这可能被视为不好的做法,但在这种情况下,我认为它可以弥补。
猜你喜欢
  • 1970-01-01
  • 2021-10-11
  • 1970-01-01
  • 2020-06-01
  • 1970-01-01
  • 2021-09-04
  • 1970-01-01
  • 1970-01-01
  • 2018-03-27
相关资源
最近更新 更多