Allow multiple methods to be provided to extend and override

This commit is contained in:
David Wheatley 2021-03-14 23:51:25 +00:00
parent 1f1c17628a
commit f3eb142a57

View File

@ -9,27 +9,36 @@
* Care should be taken to extend the correct object in most cases, a class' * Care should be taken to extend the correct object in most cases, a class'
* prototype will be the desired target of extension, not the class itself. * prototype will be the desired target of extension, not the class itself.
* *
* @example * @example <caption>Example usage of extending one method.</caption>
* extend(Discussion.prototype, 'badges', function(badges) { * extend(Discussion.prototype, 'badges', function(badges) {
* // do something with `badges` * // do something with `badges`
* }); * });
* *
* @param {Object} object The object that owns the method * @example <caption>Example usage of extending multiple methods.</caption>
* @param {String} method The name of the method to extend * extend(IndexPage.prototype, ['oncreate', 'onupdate'], function(vnode) {
* // something that needs to be run on creation and update
* });
*
* @param {object} object The object that owns the method
* @param {string|string[]} methods The name or names of the method(s) to extend
* @param {function} callback A callback which mutates the method's output * @param {function} callback A callback which mutates the method's output
*/ */
export function extend(object, method, callback) { export function extend(object, methods, callback) {
const original = object[method]; const allMethods = Array.isArray(methods) ? methods : [methods];
object[method] = function (...args) { allMethods.forEach((method) => {
const value = original ? original.apply(this, args) : undefined; const original = object[method];
callback.apply(this, [value].concat(args)); object[method] = function (...args) {
const value = original ? original.apply(this, args) : undefined;
return value; callback.apply(this, [value].concat(args));
};
Object.assign(object[method], original); return value;
};
Object.assign(object[method], original);
});
} }
/** /**
@ -37,29 +46,38 @@ export function extend(object, method, callback) {
* new function will be run every time the object's method is called. * new function will be run every time the object's method is called.
* *
* The replacement function accepts the original method as its first argument, * The replacement function accepts the original method as its first argument,
* which is like a call to 'super'. Any arguments passed to the original method * which is like a call to `super`. Any arguments passed to the original method
* are also passed to the replacement. * are also passed to the replacement.
* *
* Care should be taken to extend the correct object in most cases, a class' * Care should be taken to extend the correct object in most cases, a class'
* prototype will be the desired target of extension, not the class itself. * prototype will be the desired target of extension, not the class itself.
* *
* @example * @example <caption>Example usage of overriding one method.</caption>
* override(Discussion.prototype, 'badges', function(original) { * override(Discussion.prototype, 'badges', function(original) {
* const badges = original(); * const badges = original();
* // do something with badges * // do something with badges
* return badges; * return badges;
* }); * });
* *
* @param {Object} object The object that owns the method * @example <caption>Example usage of overriding multiple methods.</caption>
* @param {String} method The name of the method to override * extend(Discussion.prototype, ['oncreate', 'onupdate'], function(original, vnode) {
* // something that needs to be run on creation and update
* });
*
* @param {object} object The object that owns the method
* @param {string|string[]} method The name or names of the method(s) to override
* @param {function} newMethod The method to replace it with * @param {function} newMethod The method to replace it with
*/ */
export function override(object, method, newMethod) { export function override(object, methods, newMethod) {
const original = object[method]; const allMethods = Array.isArray(methods) ? methods : [methods];
object[method] = function (...args) { allMethods.forEach((method) => {
return newMethod.apply(this, [original.bind(this)].concat(args)); const original = object[method];
};
Object.assign(object[method], original); object[method] = function (...args) {
return newMethod.apply(this, [original.bind(this)].concat(args));
};
Object.assign(object[method], original);
});
} }