My goal is to have a widget object and have specific widgets extend that object. I would like to prevent people from having to call the render callback explicitly in every widget definition by somehow extending it in the parent (Widget). What is the best way to accomplish this?
var Widget = function (options) {
// super class
if (this.constructor === Widget) {
throw new Error("You can't instantiate abstract class.");
}
var widget = this.__proto__;
Widget.renderCallBack = function(){
//alert('the widget has rendered');
}
this.render = (function(){
var _render = this.render;
return function(){
_render();
Widget.renderCallBack();
}
})
}
Widget.constructor = Widget;
var SpecialWidget = function(options) {
Widget.apply(this, arguments);
}
SpecialWidget.prototype = Object.create(Widget);
SpecialWidget.constructor = SpecialWidget
SpecialWidget.prototype.render = function(){
// render something
}
new SpecialWidget(options);
In addition to my comment: If it is the same for all it doesn't have to be a callback function, just put the code to the end of the render
method if it's job is synchronous, if not use a promise but you have to think about that of method shadowing you will overwrite the parent class' render
method in the child. To avoid this you can use different name for the methods and call the parent's method from the child or use ES2015 class which has the super
keyword for reaching the parent class' methods.
Also you had a typo in your code:
SpecialWidget.prototype = Object.create(Widget);
It has to be:
SpecialWidget.prototype = Object.create(Widget.prototype);
Anyway I don't think it is a good idea in general.
var Widget = function(options) {
this.options = options || {};
};
Widget.prototype.widgetRender = function() {
// do stuff
console.log('Widget render');
// callback functionality
console.log('Widget render callback functionality');
};
Widget.constructor = Widget;
var SpecialWidget = function(options) {
Widget.apply(this, arguments);
};
SpecialWidget.prototype = Object.create(Widget.prototype);
SpecialWidget.prototype.render = function() {
// parent's render
this.widgetRender();
// do stuff
console.log('SpecialWidget render');
// callback functionality
console.log('SpecialWidget render callback functionality');
};
SpecialWidget.constructor = SpecialWidget
var sw = new SpecialWidget();
sw.render();
// ES2015
class ES6Widget {
constructor(options) {
this.options = options || {};
}
render() {
// do stuff
console.log('ES6Widget render');
// callback functionality
console.log('ES6Widget render callback functionality');
}
}
class ES6SpecialWidget extends ES6Widget {
render() {
// parent's render
super.render();
// do stuff
console.log('ES6SpecialWidget render');
// callback functionality
console.log('ES6SpecialWidget render callback functionality');
}
}
const es6sw = new ES6SpecialWidget();
es6sw.render();