ES6类构造函数不能像普通函数一样调用。根据ES6的规定,这样做应该会引发TypeError
错误。我曾经认为,类只是构造函数+原型中的函数的语法糖,但这使得它稍微有些不同。
我想知道,这背后的理由是什么?除非我漏掉了什么,否则它阻止了使用自定义的this
来调用函数,而某些模式可能希望这样做。
ES6类构造函数不能像普通函数一样调用。根据ES6的规定,这样做应该会引发TypeError
错误。我曾经认为,类只是构造函数+原型中的函数的语法糖,但这使得它稍微有些不同。
我想知道,这背后的理由是什么?除非我漏掉了什么,否则它阻止了使用自定义的this
来调用函数,而某些模式可能希望这样做。
总结一下,你的两个主要观点是:
ES6类构造函数不能像普通函数一样被调用。
它防止使用自定义的this来调用函数。
首先要注意的是,从类的运行时行为的角度来看,这些观点在功能上并没有紧密联系。例如,你可以允许 Foo()
不带 new
,但仍然使 Foo.call({})
的行为就像已经使用了 new
一样。作为函数调用的能力可以允许设置 this
,但不必如此,就像 Foo.bind({})()
会绑定一个 this
然后调用函数,但绑定的 this
将被忽略一样。
至于这个决定背后的原因,我无法给你一个主要来源,但我可以告诉你有一个很好的理由。ES6类语法是“语法糖”,但不是你脑海中可能想象的简化代码。以你的目标为例,看看这个片段。
class Parent {}
class Child extends Parent {
constructor() {
// What is "this" here?
super();
}
}
Child.call({});
这段代码应该做什么?在ES6中,super()
实际上是设置this
的方法。如果在调用super()
之前尝试访问this
,它会抛出异常。你的示例代码可能可以使用Base.call({})
,因为它没有父构造函数,所以this
被提前初始化了,但是一旦你调用一个子类,this
甚至没有一个初始值。如果你使用.call
,就没有地方可以放置那个值。
super()
之前不会得到this
?这是因为它允许ES6类语法扩展像Array
、Error
和Map
等任何其他内置构造函数类型。在标准的ES5中,这是不可能的,尽管在ES5的非标准__proto__
中可以粗略地模拟。即使使用__proto__
,扩展内置类型通常也会存在性能问题。通过在ES6类中包含此行为,JS引擎可以优化代码,以便扩展内置类型不会影响性能。Foo.call()
或Foo()
,但无论如何都必须忽略this
,以便允许扩展内置类型。Reflect.construct
仍然可以实现一些理想的模式。你具体想要什么? - BergiPromise
,除非作为构造函数 - 在调用Promise
之前省略new
是一种编程错误。关于扩展类,请注意类实例的constructor
属性已正确设置(最后一个类,可能有多个扩展),类构造函数的.prototype
属性是只读的 - 即使您可以更改构造函数的原型属性,也无法动态更改用于构造类实例的原型对象。