在扩展 Object 的 JavaScript ES6 类的构造函数中调用 super()

问题描述 投票:0回答:2

在下面,我尝试创建一个 Object 的子类,其行为类似于 Object 在使用“new”创建实例方面的行为。我当然会向我的子类添加更多方法,但下面显示了我从构造函数中调用超级构造函数的问题。

为什么我的类 Sub 的实例不像普通对象那样具有字段“x”,当以相同的方式使用“new”和相同的参数创建时?

class Sub extends Object
{ constructor (anObject)
  { super(anObject);
  }
}
var ob  = new Object ({x: 123} );
var sub = new Sub    ({x: 123} );
console.log( ob.x ); // -> 123
console.log( sub.x); // -> undefined
javascript es6-class
2个回答
5
投票

基本上,因为

Object
很特殊并且遵循不同的规则,因为它几乎是 JavaScript 中最基本的构造。

无需扩展

Object
,只需创建不带超类的对象(因为它无论如何都是一个对象)并使用
Object.assign(this, obj)
将所有属性分配给新创建的对象。

class Sub {
  constructor(obj) {
    Object.assign(this, obj);
  }
}

console.log(new Object({a: 1}));
console.log(new Sub({a: 1}));


0
投票

虽然我发现这种行为让自己感到困惑(因此无法回答更深层次的“为什么这样设计”),但它似乎是记录在案的行为。在 MDN 中写道:

当在继承 Object 的类的构造函数中通过 super() 隐式调用 Object() 时,它会初始化一个以 new.target.prototype 作为原型的新对象。传递给 super() 的任何值都会被忽略 - 例如,即使您传递一个数字,构造函数内的 this 值也不会成为 Number 实例。

规格说:

该函数在调用时执行以下步骤:

  1. 如果 NewTarget 既不是未定义的也不是活动函数对象,那么 A。返回 ? OrdinaryCreateFromConstructor(NewTarget, "%Object.prototype%").
  2. 如果 value 未定义或为 null,则返回 OrdinaryObjectCreate(%Object.prototype%)。
  3. 归来! ToObject(值)。

据我了解,虽然最后一个是您拨打

new Object(obj)
时得到的,但您在拨打
super(obj)
时得到第一个。

因此,这种行为不仅存在于 Node 中,而且存在于所有符合浏览器规范的浏览器中(我已在 Firefox 115 和 Chromium 115 中进行了验证)。

© www.soinside.com 2019 - 2024. All rights reserved.