【问题标题】:Declaring TypeScript member in prototype rather than adding to 'this'在原型中声明 TypeScript 成员而不是添加到“this”
【发布时间】:2015-01-08 21:32:37
【问题描述】:

以下打字稿:

class A {
    member = "value";
}

...编译为:

var A = (function () {
    function A() {
        this.member = "value";
    }
    return A;
})();

我想实现以下目标:

var A = (function () {
    function A() {
    }

    A.prototype.member = "value";

    return A;
})();

这样做的原因是我相信后一种构造可能更有效,因为 (1) 每次创建新实例时都不必执行赋值 this.member = "value" 语句,以及 (2) 实例内存有效负载会更小。

免责声明:我没有对这两个结构进行基准测试,所以我真的不知道情况是否如此。

所以我的问题是:是否可以使用类型脚本声明“原型成员”?

如果有人能解释一下为什么字体脚本是这样设计的?,我也很高兴。 (见§8.4.1 in the specification

我知道以这种方式声明可变成员是愚蠢的,但不可变原语的声明,如 stringnumber,应该可以在原型上设置,对吧?

可能的解决方法是:

class A {
    member: string;
}

A.prototype.member = "value";

但是,这不适用于私人会员:

class A {
    private member: string;
}

A.prototype.member = "value"; // error TS2107: 'A.member' is inaccessible.

【问题讨论】:

  • 在幕后,它本质上不是在构造函数中执行this.member = A.prototype.member 吗?我不认为这样做有性能上的好处,但也许有人肯定知道。对我来说,我宁愿不要为了极小的性能提升而牺牲代码质量。
  • 不,不是。如果您要在 prototype 上重新分配 member,那么该更改将在所有没有明确分配成员值的实例上可见。
  • 哦,是的,这是真的。我以前从未尝试将值类型放在原型上,但这是有道理的。顺便说一句,有一个performance benefit during initialization,您添加的属性越多,分配给this 的速度就越慢。
  • 甜蜜!感谢您的性能比较!
  • 顺便说一下,如果你有少量的查找,它只会在初始化过程中更快。例如,要偏移初始化 6 个字符串,我必须执行 ~30 lookups(在我的计算机上它们是绑定的)。因此,似乎在访问变量 ~5 次之后,执行此方法是不值得的。也许?所以这似乎取决于情况是否值得。我仍然建议不要打扰,因为这些微优化只会导致您的代码更难维护。

标签: javascript typescript


【解决方案1】:

是否可以使用类型脚本声明“原型成员”?

不,目前语言不允许这样做。

解决方法

当编译器不满意时……断言:

class A {
    private member: string;
}

(<any>A.prototype).member = "value"; // suppressed

为什么要这样设计类型脚本

仅仅是因为在prototype 上具有非函数 是不习惯的。

(1) 每次创建新实例时都不必执行赋值 this.member = "value" 语句,并且 (2) 实例内存负载会更小。

但是查找肯定会变慢。这是一个示例测试:http://jsperf.com/prototype-vs-this-access

【讨论】:

  • 在我看来,投射到any 不是一个好方法。然后我们会丢失该成员的使用位置(重构等)——这是我们首先使用类型脚本的主要原因之一。
  • 您能否详细说明一下“在原型上使用非函数是非意识形态的”?我不明白非惯用语是什么意思:-)
  • 即你不会在野外找到很多将成员放在prototype 上的 JavaScript 代码。我当然不记得见过任何这样写的代码
  • 真的吗?我看到了几个用例:(1)设置对象的默认值作为 $.extend () 等的替代方法。 (2) 具有许多实例的“类”的效率。
  • 这是类型脚本源代码中将非函数成员分配给原型的一个地方:github.com/Microsoft/TypeScript/blob/master/src/compiler/…
【解决方案2】:

我想出了一个可能的解决方法,它也适用于私人成员:

class A {
    private member: string;

    static __init = (() => {
        A.prototype.member = "value";
    })();
}

这很不错;所有代码都在类构造中,我避免强制转换为any,因此仍然可以跟踪对这些私有成员的引用(用于重构等)。

使用这种方法时,在类函数上声明了一个虚拟的__init 成员。不过问题不大。

【讨论】:

  • 不错的解决方案!这实际上还不错。
猜你喜欢
  • 1970-01-01
  • 2018-04-04
  • 1970-01-01
  • 1970-01-01
  • 2021-08-18
  • 2016-10-19
  • 2020-03-04
  • 1970-01-01
  • 2016-12-23
相关资源
最近更新 更多