简体   繁体   English

扩展`Object`时使用`super()`

[英]Using `super()` when extending `Object`

I'm creating a class that extends Object in JavaScript and expect super() to initialise the keys/values when constructing a new instance of this class. 我正在创建一个在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 

Why isn't foo defined as 'bar' on ext in this example? 为什么不是foo定义为'bar'ext在这个例子吗?

EDIT 编辑

Explanation : Using `super()` when extending `Object` 说明扩展`Object`时使用`super()`

Solution : Using `super()` when extending `Object` 解决方案扩展`Object`时使用`super()`

Nobody has actually explained why it doesn't work. 实际上没有人解释为什么它不起作用。 If we look at the latest spec , the Object function is defined as follows: 如果我们查看最新的规范Object函数定义如下:

19.1.1.1 Object ( [ value ] ) 19.1.1.1对象([value])

When Object function is called with optional argument value , the following steps are taken: 使用可选参数value调用Object函数时,将执行以下步骤:

  1. If NewTarget is neither undefined nor the active function, then 如果NewTarget既不是undefined也不是活动函数,那么
    1. Return ? 回来? OrdinaryCreateFromConstructor(NewTarget, "%ObjectPrototype%") . OrdinaryCreateFromConstructor(NewTarget, "%ObjectPrototype%")
  2. If value is null , undefined or not supplied, return ObjectCreate(%ObjectPrototype%) . 如果valuenullundefined或not ObjectCreate(%ObjectPrototype%) ,则返回ObjectCreate(%ObjectPrototype%)
  3. Return ! 回来了! ToObject(value) . ToObject(value)

The first step is the important one here: NewTarget refers to the function that new was called upon. 第一步是重要的一步: NewTarget指的是调用new的函数。 So if you do new Object , it will be Object . 因此,如果您执行new Object ,它将是Object If you call new ExtObject it will ExtObject . 如果你调用new ExtObject ,它将是ExtObject

Because ExtObject is not Object ( "nor the active function" ), the condition matches and OrdinaryCreateFromConstructor is evaluated and its result returned. 因为ExtObject不是Object“也不是活动函数” ),所以条件匹配并且会计算OrdinaryCreateFromConstructor并返回其结果。 As you can see, nothing is done with the value passed to the function. 如您所见,传递给函数的value没有任何作用。

value is only used if neither 1. nor 2. are fulfilled. 只有在不满足1和2的情况下才使用该value And if value is an object, it is simply returned as is, no new object is created. 如果value是一个对象,它只是按原样返回,不会创建新对象。 So, new Object(objectValue) is actually the same as Object(objectValue) : 因此, new Object(objectValue)实际上与Object(objectValue)相同:

 var foo = {bar: 42}; console.log(new Object(foo) === foo); console.log(Object(foo) === foo); 

In other words: Object does not copy the properties of the passed in object, it simply returns the object as is. 换句话说: Object不会复制传入的对象的属性,它只是按原样返回对象。 So extending Object wouldn't copy the properties either. 因此,扩展Object也不会复制属性。

You are missing the Object.assign 您缺少Object.assign

 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 

This answer works only when using the Babel transpiler. 这个答案只有在使用Babel转换器时才有效。

Because Object's constructor returns value. 因为Object的构造函数返回值。 See spec 规格

15.2.2.1 new Object ( [ value ] ) 15.2.2.1新对象([value])
When the Object constructor is called with no arguments or with one argument value, the following steps are taken: 如果在没有参数或具有一个参数值的情况下调用Object构造函数,则执行以下步骤:
... ...
8. Returns obj. 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 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM