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

Tim*_*aas 31 javascript ecmascript-6

我正在创建一个Object在JavaScript 中扩展的类,并期望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
Run Code Online (Sandbox Code Playgroud)

为什么在此示例中foo未定义为'bar'on ext

编辑

说明:扩展`Object`时使用`super()`

解决方案:在扩展`Object`时使用`super()`

Fel*_*ing 11

实际上没有人解释为什么它不起作用.如果我们查看最新的规范,该Object函数定义如下:

19.1.1.1对象([value])

Object函数被调用,可选的参数value,采取以下步骤:

  1. 如果NewTarget既不undefined是活动功能,那么
    1. 回来?OrdinaryCreateFromConstructor(NewTarget, "%ObjectPrototype%").
  2. 如果valuenull,undefined或者未提供,则返回ObjectCreate(%ObjectPrototype%).
  3. 回来了!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);
Run Code Online (Sandbox Code Playgroud)

换句话说:Object不复制传入的对象的属性,它只是按原样返回对象.所以扩展Object也不会复制属性.


Gil*_*mbo 5

您缺少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
Run Code Online (Sandbox Code Playgroud)


bar*_*san 5

这个答案只有在使用Babel转换器时才有效.

因为Object的构造函数返回值.见规格

15.2.2.1 new Object([value])
当没有参数或一个参数值调用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
Run Code Online (Sandbox Code Playgroud)

  • @barbsan这不是一个有效的答案,你使用babel来传输代码,这就是为什么它工作,在本机支持ES6的浏览器中,这将无法正常工作 (2认同)