我喜欢ES6课程,但我无法理解为什么我必须在这样的构造函数中绑定方法:
constructor() {
this.someMethod = this.someMethod.bind(this)
}
我几乎需要为任何方法做到这一点。
这是一个真正的限制还是我错过了什么?这背后的原因是什么?我知道JS中的类只是语法糖,但这可能是它们的一部分。
答案 0 :(得分:10)
引用Mark Miller对the linked esdiscuss post的回答:
早期的几个类提议都是这样做的,因为它们从es5对象的语义开始,作为闭包和类作为实例组合的特征。
这个想法是语言支持会使这种语义有效,避免了每个实例为每个方法急切分配一个闭包的需要。
然而,由于我理解的原因,这些未能获得牵引力。相反,我们转向糖,将主要的es5模式编码类转换为原型继承。最初,我们试图让这纯粹是糖,这样人们就可以毫不费力地将这种主导模式中的代码重构为类。
当我们围绕超级和建筑的详细语义进行斗争时,es6类偏离了纯糖。但是这种偏差只能防止es6类的无痛重构成为主导的es5模式。实际上,将es5模式重构为es6类仍然没有任何意义。
在zenparsing/es-function-bind#17,我们意识到了
我们仍然可以在提取时使用方法绑定 - 通过判断方法作为getter绑定的访问器安装在原型上来解释行为。然而,这种认识对于es6来说太迟了。因为它会使重构变成更危险的类 - 更多的是语义变化 - 即使我们及时想到它也不清楚它是否会飞行。相反,在装饰器设计的所有变体中,可以通过显式创建此访问器属性来编写这样的装饰器,以便装饰方法是绑定提取。然而(!),如果实现为用户土地装饰器,这比对象关闭更糟糕!在分配对象时,Objects-as-closures具有更高的分配成本。
jsperf.com/creating-stateful-objects
但是在创建对象后使用对象非常有效:
(请注意,jsperf错误地将Edge 28.14257.1000.0标识为Chrome 46.0.2486。这值得注意,因为Edge使用WeakMaps的转置表示,因此基于WeakMap的私有状态使用对Edge的惩罚要小得多。尽管如此除了这个主题之外。)
为了使提取绑定的装饰器有效,实现在某处需要某种特殊情况,以避免在立即调用方法时进行分配,而不是被观察提取。 TC39唯一需要做的就是标准化这样的装饰器,以便实现可以将它作为它们识别的内置提供。
凯文史密斯的回答:
一般来说,在使语言“更好”(对某些主观价值体系)和保持一致性之间往往存在紧张关系。我认为在这种情况下保持一致性是正确的。
也就是说,public class fields proposal将允许您将实例方法定义为
class Foo {
someMethod = () => {
// do stuff
}
}
(而不是在constructor
中执行相同操作。)