ES6类构造函数不能被称为正常函数的原因是什么?

时间:2017-06-08 22:40:22

标签: javascript ecmascript-6 prototypal-inheritance

ES6类构造函数不能被称为普通函数。根据ES6,当这样做时,应该提出TypeError。我曾经认为类只是原型中构造函数+函数的语法糖,但这使它略有不同。

我想知道,这背后的理由是什么?除非我遗漏了某些内容,否则它会阻止使用自定义this调用该函数,这可能适用于某些模式。

3 个答案:

答案 0 :(得分:0)

重新访问ES6规范,显示 如何通过组合9.2.9和9.2.1节来禁用调用没有new的类函数对象:

  

9.2.9 MakClassConstructor(F)
  ...
  3.将F的[[FunctionKind]]内部插槽设置为" classConstructor"。

并指定[[call]]方法而不是函数的[[contruct]]方法:

  

(9.2.1)2。如果F的[[FunctionKind]]内部插槽是" classConstructor",则抛出TypeError异常。

在#34; 11.2.3"功能调用"部分中没有对呼叫功能的限制。 ES5.1。

所以你没有遗漏任何东西:你不能在类构造函数上使用apply

主要的理由可能是使类扩展成为一项相当严格的练习,并检测一些早期形式的错误。例如,除了作为构造函数之外,您无法调用Promise - 并且在调用new 之前遗漏Promise 编程错误。关于扩展类,请注意正确设置了类实例的constructor属性(可能是多个扩展后的最后一个类),并且类构造函数的.prototype属性是只读的 - 您可以&#39 ; t动态更改用于构造类实例的原型对象,即使您可以更改构造函数的prototype属性。

我曾经认为课程是语法糖,但已经离开了概念。

答案 1 :(得分:0)

总结一下,你的两个要点是

  1.   

    ES6类构造函数不能被称为普通函数。

  2.   

    它阻止使用自定义调用该函数

  3. 首先要注意的是,从类的运行时行为的角度来看,那些点在功能上并没有联系在一起。例如,您可以允许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的内容。如果您在调用this之前尝试访问super(),则会抛出异常。您的示例代码可能Base.call({})一起使用,因为它没有父构造函数,所以this会在前面初始化,但只要您调用子类, this预先没有价值。如果您使用.call,则无法放置该值。

    那么接下来的问题是,为什么在this之前,子课程没有得到super()?这是因为它允许ES6类语法扩展内置类型,如ArrayErrorMap以及任何其他内置构造函数类型。在标准 ES5中,这是不可能的,尽管ES5中的非标准__proto__可以模拟粗略。即使使用__proto__,扩展内置类型通常也是一个性能问题。通过在ES6类中包含此行为,JS引擎可以优化代码,以便扩展内置类型工作而不会影响性能。

    因此,对于您的问题,是的,他们可以允许Foo.call()Foo(),但无论如何都必须忽略this才能扩展内置类型。

答案 2 :(得分:0)

  

这背后的理由是什么?

这是一种保障。当您在没有function的情况下调用ES5 new构造函数时,它会执行非常不受欢迎的操作,无声地失败。抛出异常有助于您发现错误。

当然,他们可以选择调用语法与构造相同,但强制使用new关键字是一件好事,可以帮助我们轻松识别实例化。

  

它阻止使用自定义this调用该函数,这可能适用于某些模式。

是的,这是ES6的根本改变。 this值由超类初始化,允许具有内部插槽的子类内置 - 有关详细信息,请参阅here。这与传递自定义此参数有冲突,为了保持一致性,我们绝不允许这样做。