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

问题描述 投票:10回答:3

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()表现完全正常。

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

javascript methods ecmascript-6 shorthand
3个回答
10
投票

specification对解释这个并不是很直接,但我们可以遵循一个短链..

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

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

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

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

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


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

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

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

让methodDef成为MethodDefinition的DefineMethod with argument object。

这就是DefineMethod只用一个参数,对象。让我们看一下DefineMethod - 这就是我们需要的:

带参数对象和可选参数functionPrototype。


  1. 如果functionPrototype作为参数传递,请将类型设为Normal;否则,请善待Method
  2. 让闭包为FunctionCreate(kind,[更多参数剪断])。

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

  1. 如果善良不是Normal,让allocKind成为"non-constructor"
  2. 另外,让allocKind成为"normal"
  3. 设F为FunctionAllocate([其他参数剪切],allocKind)。

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

  1. 如果functionKind是"normal",请让needsConstruct为true。
  2. 否则,让needsConstruct为假。

  1. 设F是新创建的ECMAScript函数对象,其中内部插槽列在Table 27中。所有这些内部插槽都初始化为未定义。

  1. 如果needsConstruct为true,那么 一个。将F的[[Construct]]内部方法设置为9.2.2中指定的定义。 湾将F的[[ConstructorKind]]内部插槽设置为"base"

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

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

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

..但是现在你们知道他们不是正式的建造者。


2
投票

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

Reference here


0
投票

似乎最初的讨论发生在这里:https://github.com/rwaldron/tc39-notes/blob/master/es6/2012-07/july-26.md

MM:三个原因:

  • 内在的先例
  • 使用方法作为构造函数通常是无稽之谈
  • 要冻结一个类,我必须冻结原型上方法的.prototype!

AWB:建议:对于类和对象文字,简明的方法应该是相同的

  • 严格
  • enumerability
  • 施工性
  • 属性

这就是类方法和对象方法变得不可构造的方式

© www.soinside.com 2019 - 2024. All rights reserved.