Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript: Extend a Function

The main reason why I want it is that I want to extend my initialize function.

Something like this:

// main.js  window.onload = init(); function init(){      doSomething(); }  // extend.js  function extends init(){     doSomethingHereToo(); } 

So I want to extend a function like I extend a class in PHP.

And I would like to extend it from other files too, so for example I have the original init function in main.js and the extended function in extended.js.

like image 550
Adam Halasz Avatar asked Jan 02 '11 12:01

Adam Halasz


People also ask

Can I extend a function in JavaScript?

If you're assigning these functions to some property somewhere, you can wrap the original function and put your replacement on the property instead: // Original code in main. js var theProperty = init; function init(){ doSomething(); } // Extending it by replacing and wrapping, in extended.

How do you extend in JavaScript?

The extends keyword can be used to extend the objects as well as classes in JavaScript. It is usually used to create a class which is child of another class. Syntax: class childclass extends parentclass {...}

What does it mean to extend a function?

To "extend f", means to define a function g, whose domain contains the domain of f, such that g(x)=f(x) for all x in the domain of f.


1 Answers

With a wider view of what you're actually trying to do and the context in which you're doing it, I'm sure we could give you a better answer than the literal answer to your question.

But here's a literal answer:

If you're assigning these functions to some property somewhere, you can wrap the original function and put your replacement on the property instead:

// Original code in main.js var theProperty = init;  function init(){      doSomething(); }  // Extending it by replacing and wrapping, in extended.js theProperty = (function(old) {     function extendsInit() {         old();         doSomething();     }      return extendsInit; })(theProperty); 

If your functions aren't already on an object, you'd probably want to put them there to facilitate the above. For instance:

// In main.js var MyLibrary = {     init: function init() {     } };  // In extended.js (function() {     var oldInit = MyLibrary.init;     MyLibrary.init = extendedInit;     function extendedInit() {         oldInit.call(MyLibrary); // Use #call in case `init` uses `this`         doSomething();     } })(); 

But there are better ways to do that. Like for instance, providing a means of registering init functions.

// In main.js var MyLibrary = (function() {     var initFunctions = [];     return {         init: function init() {             var fns = initFunctions;             initFunctions = undefined;             for (var index = 0; index < fns.length; ++index) {                 try { fns[index](); } catch (e) { }             }         },         addInitFunction: function addInitFunction(fn) {             if (initFunctions) {                 // Init hasn't run yet, remember it                 initFunctions.push(fn);             } else {                 // `init` has already run, call it almost immediately                 // but *asynchronously* (so the caller never sees the                 // call synchronously)                 setTimeout(fn, 0);             }         }     }; })(); 

Here in 2020 (or really any time after ~2016), that can be written a bit more compactly:

// In main.js const MyLibrary = (() => {     let initFunctions = [];     return {         init() {             const fns = initFunctions;             initFunctions = undefined;             for (const fn of fns) {                 try { fn(); } catch (e) { }             }         },         addInitFunction(fn) {             if (initFunctions) {                 // Init hasn't run yet, remember it                 initFunctions.push(fn);             } else {                 // `init` has already run, call it almost immediately                 // but *asynchronously* (so the caller never sees the                 // call synchronously)                 setTimeout(fn, 0);                 // Or: `Promise.resolve().then(() => fn());`                 // (Not `.then(fn)` just to avoid passing it an argument)             }         }     }; })(); 
like image 50
T.J. Crowder Avatar answered Nov 03 '22 00:11

T.J. Crowder