构造函数使用ES6简写表示法表现不同

时间:2016-12-16 22:08:07

标签: javascript methods ecmascript-6 shorthand

ES6引入了shorthand notation来初始化具有函数和属性的对象。

// ES6 shorthand notation
const obj1 = {
    a(b) {
        console.log("ES6: obj1");
    }
};

// ES5
var obj2 = {
    a: function a(b) {
        console.log("ES5: obj2");
    }
};

obj2.a();
obj1.a();

new obj2.a();
new obj1.a();

然而,正如您所看到的,这些不同的符号表现不同。如果我在浏览器中new obj1.a()(测试过Chrome和Firefox),我会得到TypeError: obj1.a is not a constructornew obj2.a()表现完全正常。

这里发生了什么?有没有人有解释和/或文档/规范的链接?

3 个答案:

答案 0 :(得分:10)

specification并非直接解释这一点,但我们可以遵循一条短链......

我们将从EvaluateNew开始,因为这是我们想知道的行为。第7步显然是我们在这里寻找的那个:

  
      
  1. 如果IsConstructor(构造函数 false ,则抛出 TypeError 异常。
  2.   

所以IsConstructor是我们接下来要看的地方。

摘要和步骤都描述了这一点:

  

抽象操作IsConstructor确定参数(必须是ECMAScript语言值)是否是具有[[Construct]]内部方法的函数对象。

           
      
  1. 如果Type(参数)不是Object,则返回 false
  2.   
  3. 如果参数有[[Construct]]内部方法,请返回 true
  4.   
  5. 返回 false
  6.   

因此,从它的外观来看,我们的obj1.a没有[[Construct]]内部方法。让我们来看看它不应该有一个......

以下是我们正在寻找的内容,PropertyDefinitionEvaluation。第一步在这里很有用:

  

让methodDef为MethodDefinition的DefineMethod,参数为 object

只用一个参数 object 调用DefineMethod。让我们看一下DefineMethod - 这就是我们需要的东西:

  

使用参数对象和可选参数functionPrototype。

           
      
  1. 如果 functionPrototype 作为参数传递,请将 kind 设为Normal;否则让 kind 成为Method
  2.   
  3. 闭包成为FunctionCreate(亲切的, [更多参数剪切] )。
  4.   

由于 functionPrototype not 作为参数传递,因此类型为Method。让我们来看看FunctionCreate对此的作用:

  
      
  1. 如果 kind 不是Normal,请将 allocKind 设为"non-constructor"
  2.   
  3. 否则,让 allocKind "normal"
  4.   
  5. 设F为FunctionAllocate( [其他参数剪断] allocKind )。
  6.   

现在我们越来越近了!我们只需要查看FunctionAllocate使用 allocKind (按照上述步骤"non-constructor"),这就是函数所有内部方法等等。

  
      
  1. 如果 functionKind "normal",请 needsConstruct true
  2.   
  3. 否则,让 needsConstruct false
  4.               
        
    1. F 成为新创建的ECMAScript函数对象,其内部插槽列在Table 27中。所有这些内部插槽都初始化为未定义
    2.               
          
      1. 如果 needsConstruct true ,那么

             

        一个。将 F 的[[Construct]]内部方法设置为9.2.2中指定的定义。

             

        湾将 F 的[[ConstructorKind]]内部插槽设置为"base"

      2.   

最后!如果我们完成相关步骤,我们可以看到,因为 functionKind 不是"normal" needsConstruct 变为 false ,所以永远不会分配[[Construct]]内部方法!然后IsConstructor看到并返回false,因此EvaluateNew失败。

MDN非常简单地描述了这种行为:

  

所有方法定义都不是构造函数,如果您尝试实例化它们,则会抛出TypeError。

..但现在你正式知道他们不是的构造函数。

答案 1 :(得分:2)

使用此语法声明的方法不是可构造的

Reference here

答案 2 :(得分:0)

原始讨论似乎在这里进行: https://github.com/rwaldron/tc39-notes/blob/master/es6/2012-07/july-26.md

  

MM:这样做的三个原因:

     
      
  • 内置的先例
  •   
  • 使用方法作为构造函数通常是胡说八道
  •   
  • 要冻结类,我必须冻结原型上方法的.prototype!
  •   

  

AWB:建议:类和对象文字的简洁方法应该相同

     
      
  • 严格
  •   
  • 可枚举性
  •   
  • 可构造性
  •   
  • 属性
  •   

这就是类方法和对象方法都是不可构造的