构造函数使用 ES6 shorthand 表示法表现不同
Constructor behaving differently using ES6 shorthand notation
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 constructor
。 new obj2.a()
表现完全正常。
这里发生了什么?有人有解释吗,and/or 链接到 documentation/specification?
使用此语法声明的方法不可构造
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 be Method
.
- 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 的关系(按照上述步骤是 "non-constructor"
),这就是赋予函数所有内部方法的原因等等。
- 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 不是 "normal"
,needsConstruct 变成 false ,所以 [[Construct]] 内部方法永远不会被赋值!然后 IsConstructor 发现 returns 错误,因此 EvaluateNew 失败。
MDN 非常简单地描述了这种行为:
All method definitions are not constructors and will throw a TypeError if you try to instantiate them.
..但现在你知道如何他们不是构造函数,正式的。
原来的讨论似乎发生在这里:
https://github.com/rwaldron/tc39-notes/blob/master/es6/2012-07/july-26.md
MM: three reasons for this:
- precedent in builtins
- using a method as a constructor is generally nonsense
- to freeze a class, I have to freeze the .prototype of the methods on the prototype!!
和
AWB: suggestion: concise methods should be the same for both classes and object literals
- strictness
- enumerability
- constructability
- attributes
这就是 class 方法和对象方法都变得不可构造的原因
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 constructor
。 new obj2.a()
表现完全正常。
这里发生了什么?有人有解释吗,and/or 链接到 documentation/specification?
使用此语法声明的方法不可构造
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 的关系(按照上述步骤是 "non-constructor"
),这就是赋予函数所有内部方法的原因等等。
- 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 不是 "normal"
,needsConstruct 变成 false ,所以 [[Construct]] 内部方法永远不会被赋值!然后 IsConstructor 发现 returns 错误,因此 EvaluateNew 失败。
MDN 非常简单地描述了这种行为:
All method definitions are not constructors and will throw a TypeError if you try to instantiate them.
..但现在你知道如何他们不是构造函数,正式的。
原来的讨论似乎发生在这里: https://github.com/rwaldron/tc39-notes/blob/master/es6/2012-07/july-26.md
MM: three reasons for this:
- precedent in builtins
- using a method as a constructor is generally nonsense
- to freeze a class, I have to freeze the .prototype of the methods on the prototype!!
和
AWB: suggestion: concise methods should be the same for both classes and object literals
- strictness
- enumerability
- constructability
- attributes
这就是 class 方法和对象方法都变得不可构造的原因