简体   繁体   English

为什么在 ES6 中创建的对象的方法没有绑定到它的类?

[英]Why aren't methods of an object created with class bound to it in ES6?

I like ES6 classes but I can't understand why I have to bind methods in the constructor:我喜欢 ES6 类,但我不明白为什么我必须在构造函数中绑定方法:

constructor() {
    this.someMethod = this.someMethod.bind(this)
}

I need to do this almost for any method.我几乎需要为任何方法执行此操作。

Is this a real limitation or am I missing something?这是一个真正的限制还是我错过了什么? What is the reason behind this?这背后的原因是什么? I know that classes in JS are only syntactic sugar but this could have been part of them.我知道 JS 中的类只是语法糖,但这可能是其中的一部分。

Quoting Mark Miller's answer to the linked esdiscuss post here:在这里引用 Mark Miller 对链接的 esdiscuss 帖子的回答:

Several of the early class proposals did so, as they were starting with the semantics of es5 objects-as-closures and classes as compositions-of-instance-traits.一些早期的类提案是这样做的,因为它们从 es5 对象作为闭包和类作为实例特征组合的语义开始。

doku.php?do=search&id=traits doku.php?do=search&id=traits

The idea was that language support would make this semantics efficient, avoiding the need to eagerly allocate a closure per method per instance.这个想法是语言支持将使这种语义有效,避免需要急切地为每个实例的每个方法分配一个闭包。

However, for reasons I understand, these failed to gain traction.然而,出于我理解的原因,这些未能获得关注。 Instead, we moves towards sugar for the dominant es5 pattern of encoding classes into prototype inheritance.相反,我们将主要的 es5 模式转向将类编码为原型继承的糖。 Initially, we tried to have this purely be sugar, so that people could painlessly refactor code in that dominant pattern into classes.最初,我们试图让这纯粹是糖,以便人们可以轻松地将这种主导模式中的代码重构为类。

As we wrestled with the detailed semantics around super and construction, es6 classes deviated from being pure sugar.当我们与围绕 super 和构造的详细语义搏斗时,es6 类偏离了纯糖。 But this deviation only prevents painless refactoring from es6 classes into the dominant es5 pattern.但是这种偏差只会阻止从 es6 类到主导的 es5 模式的无痛重构。 Practically, it remains painless to refactor from the es5 pattern into es6 classes.实际上,从 es5 模式重构为 es6 类仍然很容易。

At zenparsing/es-function-bind#17 we realizedzenparsing/es-function-bind#17我们意识到

we could still have had methods bind on extraction -- accounting for the behavior by decreeing that methods are installed on the prototype as accessors whose getter binds.我们仍然可以在提取时绑定方法——通过下令将方法安装在原型上作为其 getter 绑定的访问器来解释行为。 However, this realization came too late for es6.然而,对于 es6 来说,这种认识来得太晚了。 Since it would have made the refactoring into classes more hazardous -- more of a semantic change -- it is not clear it would have flown even if we had thought of it in time.由于它会使重构为类更加危险——更多的是语义变化——即使我们及时想到它,也不清楚它是否会成功。 Instead, under all variations of the decorator designs, one can write such a decorator so that decorated methods are bind-on-extraction, by explicitly creating this accessor property.相反,在装饰器设计的所有变体下,我们可以编写这样的装饰器,以便通过显式创建此访问器属性来将装饰方法绑定到提取。 However(!), if implemented as a user-land decorator, this has much worse performance than objects-as-closures!!然而(!),如果实现为用户空间装饰器,这比对象作为闭包的性能要差得多! Objects-as-closures have higher allocation cost when allocating the object.对象作为闭包在分配对象时具有更高的分配成本。

jsperf.com/creating-stateful-objects jsperf.com/creating-stateful-objects

But are quite efficient at using the object once the object is created:但是在创建对象后使用对象非常有效:

jsperf.com/strict-where-state jsperf.com/strict-where-state

(Note that jsperf is misidentifying Edge 28.14257.1000.0 as Chrome 46.0.2486. This is worth noting because Edge uses the transposed representation for WeakMaps, and so WeakMap-based usage of private state has much less penalty on Edge. Though this is besides the point of this thread.) (请注意,jsperf 将 Edge 28.14257.1000.0 错误地识别为 Chrome 46.0.2486。这是值得注意的,因为 Edge 使用 Wea​​kMap 的转置表示,因此基于 WeakMap 的私有状态使用对 Edge 的惩罚要小得多。尽管这是除了这个线程的要点。)

To make a decorator for binding-on-extraction efficient, an implementation would need some kind of special case somewhere to avoid the allocation when the method is being immediately invoked, rather than being observably extracted.为了使提取时绑定的装饰器高效,实现将需要某种特殊情况在某处避免在方法被立即调用时分配,而不是被可观察地提取。 The only thing TC39 needs to do to enable this is to standardize such a decorator so that implementations can provide it as a builtin that they recognize. TC39 需要做的唯一一件事就是标准化这样的装饰器,以便实现可以将它作为他们识别的内置函数提供。

And Kevin Smith's answer:和凯文史密斯的回答:

In general, there is often a tension between making the language "better" (for some subjective value system) and maintaining consistency.通常,在使语言“更好”(对于某些主观价值系统)和保持一致性之间通常存在紧张关系。 I think maintaining consistency was the right call in this case.我认为在这种情况下保持一致性是正确的要求。


That said, the public class fields proposal will allow you to define instance methods as也就是说,公共类字段提案将允许您将实例方法定义为

class Foo {
  someMethod = () => {
    // do stuff
  }
}

(instead of doing the same in the constructor ). (而不是在constructor中做同样的事情)。

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

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