简体   繁体   English

JavaScript ES6 - 如何像可以用“new”构造的那样超级构造对象?

[英]JavaScript ES6 - How to super-construct Object like it can be constructed with "new"?

class Foo extends Object {
    constructor(value) {
        super(value)
    }
}

a = new Object(10);
b = new Foo(10);

console.log(a.valueOf() === b.valueOf()) // false, why?

Last time I checked, creating a class that extends another, and doing nothing but calling the super-class' constructor using this within the sub-class' constructor affects this the same way that the instance of the super class created using new is affected.我最后一次检查,创建扩展另一个类,做什么,但使用的构造函数调用超一流this子类中的构造函数会影响this相同的方式,超类的实例使用创建new的影响。

So why this inconsistency, and is there any work around?那么为什么会出现这种不一致,是否有任何解决方法?

I'm trying to create a class that instantiating returns whatever value was passed into the first argument of its constructor, but with additional properties assigned.我正在尝试创建一个类,该类实例化返回传递给其构造函数的第一个参数的任何值,但分配了其他属性。

The problem is that Object only coerces to object when the NewTarget is undefined or is not the Object constructor itself.问题是Object仅在 NewTarget 未定义或不是Object构造函数本身时才强制Object Otherwise, it returns an ordinary object which inherits from NewTarget's .prototype .否则,它返回一个从 NewTarget 的.prototype继承的普通对象。

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%).如果值为null、未定义或未提供,则返回ObjectCreate (%ObjectPrototype%)。
  3. Return ToObject ( value ).返回到对象)。

In your case, when you instantiate Foo , the NewTarget will be Foo , so the this value will be initialized to Object.create(Foo.prototype) , not new Object(value) .在您的情况下,当您实例化Foo , NewTarget 将是Foo ,因此this值将被初始化为Object.create(Foo.prototype) ,而不是new Object(value)

So you can't do this directly.所以你不能直接这样做。 But there is the manual approach:但是有手动方法:

 function valueOf(value) { var result; [Boolean, Number, String, Symbol, Object].some(function(F) { try { result = F.prototype.valueOf.call(value); return true; } catch(err) { return false } }); return result; } class Foo { constructor(value) { if(Object(value) === value) // Is an object return value; /* or maybe `return this`? */ switch(typeof value) { case 'boolean': return Reflect.construct(Boolean, [value], Foo); case 'number': return Reflect.construct(Number, [value], Foo); case 'string': return Reflect.construct(String, [value], Foo); case 'symbol': return Reflect.construct(Symbol, [value], Foo); } // For undefined and null, let it return `this` } } console.log(valueOf(new Object(true)) === valueOf(new Foo(true))); console.log(valueOf(new Object(10)) === valueOf(new Foo(10))); console.log(valueOf(new Object("ab")) === valueOf(new Foo("ab")));

Note you need a custom function to get the appropriate value.请注意,您需要一个自定义函数来获取适当的值。 That's because, even if new Foo('10') returns a number object, it inherits from Foo.prototype , which does not include Number.prototype in its prototypical chain.这是因为,即使new Foo('10')返回一个数字对象,它也继承自Foo.prototype ,它的原型链中不包括Number.prototype But I guess this is intended, otherwise you could directly return Object(value) .但我想这是有意的,否则你可以直接return Object(value)

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

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