javascript - 构造函数使用 ES6 速记符号表现不同

标签 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();

但是,如您所见,这些不同的表示法表现不同。如果我在浏览器(经过测试的 Chrome 和 Firefox)中执行 new obj1.a(),我会得到一个 TypeError: obj1.a is not a constructornew obj2.a() 表现完全正常。

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

最佳答案

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

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

  1. If IsConstructor(constructor) is false, throw a TypeError exception.

所以 IsConstructor是我们下一步需要看的地方。

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

The abstract operation IsConstructor determines if argument, which must be an ECMAScript language value, is a function object with a [[Construct]] internal method.


  1. If Type(argument) is not Object, return false.
  2. If argument has a [[Construct]] internal method, return true.
  3. Return false.

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

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

Let methodDef be DefineMethod of MethodDefinition with argument object.

调用DefineMethod只有一个参数,object。让我们看看 DefineMethod - 这是我们需要的:

With parameters object and optional parameter functionPrototype.


  1. If functionPrototype was passed as a parameter, let kind be Normal; otherwise let kind be Method.
  2. Let closure be FunctionCreate(kind, [more arguments snipped]).

因为 functionPrototype 没有作为参数传递,所以类型是Method。让我们看看是什么FunctionCreate这样做:

  1. If kind is not Normal, let allocKind be "non-constructor".
  2. Else, let allocKind be "normal".
  3. Let F be FunctionAllocate([other arguments snipped], allocKind).

现在我们越来越接近了!我们只需要看看 FunctionAllocate使用 allocKind(根据上述步骤,它是 “非构造函数”),这就是赋予函数所有内部方法等的原因。

  1. If functionKind is "normal", let needsConstruct be true.
  2. Else, let needsConstruct be false.

  1. Let F be a newly created ECMAScript function object with the internal slots listed in Table 27. All of those internal slots are initialized to undefined.

  1. If needsConstruct is true, then

    a. Set F's [[Construct]] internal method to the definition specified in 9.2.2.

    b. Set the [[ConstructorKind]] internal slot of F to "base".

终于!如果我们完成相关步骤,我们可以看到,由于 functionKind 不是“正常”needsConstruct 变为false,因此永远不会分配 [[Construct]] 内部方法!然后 IsConstructor 发现并返回 false,因此 EvaluateNew 失败。

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

All method definitions are not constructors and will throw a TypeError if you try to instantiate them.

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

关于javascript - 构造函数使用 ES6 速记符号表现不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41193117/

相关文章:

javascript - 同构 (SmartClient) ListGrid 不允许 Div 标签溢出(与 Twitter Bootstrap 的多选冲突)

java - 类方法与主要方法

python - 无法在数据框中基于其他列创建列。尝试了几种选择 - 没有一个有效。 (Python、 Pandas )

javascript - 未调用鼠标移动函数

javascript - 如何导入使用 ES2015 语法的文件导出的所有内容?有通配符吗?

javascript - 水平数据更新不适用于滚动

javascript - 当有一个数字参数传递给 toString 时,这意味着什么?

javascript - HTML/JavaScript - 如何隐藏链接和光标?

java - J Something something = new Something().something else;

javascript - 从嵌套对象和数组的巨大 JSON 中以编程方式解构特定属性的最佳且最有效的方法