I am refactoring some code from an older ES5 codebase, where I was doing the following:
function ObjectCreatorFunction() {
this.someProperty= {};
}
/*
* Static method, to extend the object passed as a parameter with the
* ObjectCreatorFunction instance properties and methods
*/
ObjectCreatorFunction.extend = function extend(object) {
var key;
ObjectCreatorFunction.call(object);
for (key in ObjectCreatorFunction.prototype) {
if (ObjectCreatorFunction.prototype.hasOwnProperty(key)) {
if (!object.hasOwnProperty(key)) {
object[key] = ObjectCreatorFunction.prototype[key];
}
}
}
return object;
};
ObjectCreatorFunction.prototype.someMethod = function someMethod() {...}
//etc
I am trying to do the same with an ES6 rewrite, so I a have this
class ClassName{
constructor() {
this.someProperty= {};
}
static extend(object) {
let key;
ClassName.constructor.call(object);
for (key in ClassName.prototype) {
if (ClassName.prototype.hasOwnProperty(key)) {
if (!object.hasOwnProperty(key)) {
object[key] = ClassName.prototype[key];
}
}
}
return object;
}
someMethod() {...}
//etc
}
My problem is that the line
ClassName.constructor.call(object);
does not work as intended, i.e. The passed object does not get the instance properties of the class.
I have tried s few ways to rewrite this (even some unorthodox ones) to no avail.
How do I extend an object with a class' instance properties, using ES6?
DISCLAIMER:
My code is passed through a transpiling process, with babel and webpack. In case it has any effect to how classes work internally.
No, this does not work with class
syntax. It's a bit more than just syntactic sugar. The prototypical inheritance stayed the same, but the initialisation of instances works differently now especially for inherited classes, and you cannot invoke a constructor without new
to not create a new instance.
I would recommend to be explicit about your mixin, and give it an init
method:
class Mixin {
constructor(methods) {
this.descriptors = Object.getOwnPropertyDescriptors(methods);
}
extend(object) {
for (const p in this.descriptors)) {
if (Object.prototype.hasOwnProperty.call(object, p)) {
if (process.env.NODE_ENV !== 'production') {
console.warn(`Object already has property "${p}"`);
}
} else {
Object.defineProperty(object, p, this.descriptors[p]);
}
}
}
}
// define a mixin:
const xy = new Mixin({
initXY() {
this.someProperty= {};
},
someMethod() { … }
});
// and use it:
class ClassName {
constructor() {
this.initXY();
}
}
xy.extend(ClassName.prototype);