我正在创建一个在JavaScript中扩展Object
的类,并期望super()
在构造此类的新实例时初始化键/值。
class ExtObject extends Object {
constructor(...args) {
super(...args);
}
}
const obj = new Object({foo:'bar'});
console.log(obj); // { foo: 'bar' }
const ext = new ExtObject({foo:'bar'});
console.log(ext); // ExtObject {}
console.log(ext.foo); // undefined
在此示例中,为什么foo
不在'bar'
上定义为ext
?
编辑
答案 0 :(得分:11)
实际上没有人解释为什么它不起作用。如果我们查看at the latest spec,则Object
函数的定义如下:
19.1.1.1对象([值])
使用可选参数
Object
调用value
函数时,将执行以下步骤:
- 如果
NewTarget
既不是undefined
也不是活动函数,则
- 返回?
OrdinaryCreateFromConstructor(NewTarget, "%ObjectPrototype%")
。- 如果
value
是null
,undefined
或未提供,请返回ObjectCreate(%ObjectPrototype%)
。- 返回!
ToObject(value)
。
第一步很重要:NewTarget
指的是调用new
的函数。因此,如果您执行new Object
,它将是Object
。如果您致电new ExtObject
,它将致电ExtObject
。
由于ExtObject
不是Object
(“不是活动函数” ),条件匹配,并且对OrdinaryCreateFromConstructor
进行了评估并返回了结果。如您所见,传递给函数的value
并没有任何作用。
value
仅在1.和2.都不满足的情况下使用。并且如果value
是一个对象,则仅按原样返回它,则不会创建任何新对象。因此,new Object(objectValue)
实际上与Object(objectValue)
相同:
var foo = {bar: 42};
console.log(new Object(foo) === foo);
console.log(Object(foo) === foo);
换句话说:Object
不会复制传入对象的属性,而只是按原样返回对象。因此,扩展Object
也不会复制属性。
答案 1 :(得分:5)
class ExtObject extends Object {
constructor(...args) {
super(...args);
Object.assign(this, ...args);
}
}
const obj = new Object({foo:'bar'});
console.log(obj); // { foo: 'bar' }
const ext = new ExtObject({foo:'bar'});
console.log(ext); // { foo: 'bar' }
console.log(ext.foo); // bar
答案 2 :(得分:5)
此答案仅在使用Babel编译器时有效。
因为对象的构造函数返回值。参见spec
15.2.2.1新对象([值])
在不带参数或带一个参数值的情况下调用Object构造函数时,将执行以下步骤:
...
8. 返回obj。
class ExtObject extends Object {
constructor(...args) {
return super(...args);
}
}
const obj = new Object({foo:'bar'});
console.log(obj); // { foo: 'bar' }
const ext = new ExtObject({foo:'bar'});
console.log(ext); // { foo: 'bar' }
console.log(ext.foo); // bar