Object Spread {...o}
only considers enumerable properties.
From MDN (emphasis mine):
Spread in object literals
The Rest/Spread Properties for ECMAScript proposal (ES2018) added spread properties to object literals. It copies own enumerable properties from a provided object onto a new object.
The prototype
property of classes and function is not enumerable. Therefore, in const Bar = {...Foo}
, Bar
will not have a prototype
property. That is precisely why you get
error: Uncaught TypeError: Cannot set property 'id' of undefined
Now, to get the code closer to what you want, you could write
const Bar = {...Foo, prototype: Foo.prototype};
However, now Bar
will behave differently from Foo
because its prototype
property will be enumerable.
So we could revise this and write
const Bar = {...Foo};
Object.defineProperty(Bar, 'prototype', {value: Foo.protoype, enumerable: false});
// `enumerable` defaults to `false` using this API, just being explicit for exposition.
However, your next statement, new B
will still fail because B
is still not a class object or a function object and therefore cannot be used with the new operator.
Without more context it is difficult to tell why you actually want to do this.
The most straightforward approach would be to write the following
class Foo {
id = 'Foo';
constructor() {
console.log(this.id);
}
}
class Bar extends Foo {
id = 'Bar';
}
new Foo() // logs 'Foo'
new Bar() // logs 'Bar'
If you would like to avoid using inheritance, there are other alternatives, but it is not clear which ones are appropriate because the question lacks sufficient context to determine this. For example, if you only want to mock objects created via new Foo
, then you could mock them trivially using a helper function that just overwrites the property with the test value, if you want to mock Foo
itself, that is to say the class object, then the alternatives would be different.