The following code, though cumbersome, allows me to define a prototype with a simple property that gets inherited by objects using the prototype:
const SCXMLState = Object.setPrototypeOf(
Object.defineProperties({
addChild() { }
isState: true // an inherited property & value
},{
isSCXML: {
get() { return this.nodeName==='scxml' }
},
id: {
get() {
return this.getAttribute('id') || (this.isSCXML ? '(scxml)' : null);
}
}
}),
Element.prototype
);
const markup = `<scxml xmlns="http://www.w3.org/2005/07/scxml" />`;
const xmldoc = (new DOMParser).parseFromString(markup, "text/xml");
const scxml = xmldoc.documentElement;
Object.setPrototypeOf(scxml, SCXMLState);
console.log({id: scxml.id, isState: scxml.isState});
// {id: '(scxml)', isState: true}
It seems more elegant (less typing, more visually clear) to use classes and inheritance…but instance fields like isState
are not inherited via the prototype, but set on instances. Since I'm not creating the instance using new
, the instance field does not work:
class SCXMLState extends Element {
addChild() { }
isState = true;
get isSCXML() {
return this.nodeName==='scxml';
}
get id() {
return this.getAttribute('id') || (this.isSCXML ? '(scxml)' : null);
}
}
const markup = `<scxml xmlns="http://www.w3.org/2005/07/scxml" />`;
const xmldoc = (new DOMParser).parseFromString(markup, "text/xml");
const scxml = xmldoc.documentElement;
Object.setPrototypeOf(scxml, SCXMLState.prototype);
console.log({id: scxml.id, isState: scxml.isState});
// {id: '(scxml)', isState: undefined}
Note that while the rest of the code works, the isState
instance field is not inherited, showing undefined
instead of true
.
Is there an alternative, hopefully ~cleaner (simpler, less typing, encapsulated) syntax to define inherited instance properties for class instances, other than:
SCXMLState.prototype.isState = true