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 constructor
。 new obj2.a()
表现完全正常。
这里发生了什么?有没有人有解释和/或文档/规范的链接?
最佳答案
specification不是很直接地解释这一点,但我们可以遵循一个短链..
我们将从 EvaluateNew 开始,因为这是我们想知道的行为。第 7 步显然是我们在这里寻找的步骤:
- 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.
- If Type(argument) is not Object, return false.
- If argument has a [[Construct]] internal method, return true.
- 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.
- If functionPrototype was passed as a parameter, let kind be
Normal
; otherwise let kind beMethod
.- Let closure be FunctionCreate(kind, [more arguments snipped]).
因为 functionPrototype 没有作为参数传递,所以类型是Method
。让我们看看是什么FunctionCreate这样做:
- If kind is not
Normal
, let allocKind be"non-constructor"
.- Else, let allocKind be
"normal"
.- Let F be FunctionAllocate([other arguments snipped], allocKind).
现在我们越来越接近了!我们只需要看看 FunctionAllocate使用 allocKind(根据上述步骤,它是 “非构造函数”
),这就是赋予函数所有内部方法等的原因。
- If functionKind is
"normal"
, let needsConstruct be true.- Else, let needsConstruct be false.
- 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.
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/