简体   繁体   中英

How to write simple, extensible, modular Javascript

I need a mechanism whereby people can extend my base code with their own modules - but I'm struggling to come-up with a simple mechanism to do that.

Example: a function called 'test' which users can extend. Each user module is loaded after the original - so each one needs to build on the last (the order they're loaded should not matter or can be controlled by naming)

I started to play with something like this

var test = function() { // the master function
    console.log("1");
}

var ltest = test; // module 1
var test = function() {
    ltest();
    console.log("2");
}

var ltest2 = test; // module 2
var test = function() {
    ltest2();
    console.log("3");
}

Then, when 'test' is called, it will run everyone's code (assuming no-one forgot their callback!!)

That works, but it relies on each module declaring it's own, unique 'callback' variable (ltest, ltest2) - if someone uses the same variable, we'll get a 'call stack exceeded' as those variables are global in scope...

Can anyone suggest a cleverer/better system - or point me to some examples of the same thing?

There's loads of material on inheritance but I don't want to create new things which extend the old one - I just want to extend the old one!!

ps taking the anonymous function stuff from the module pattern - I got this

var test = function() {
    console.log("1");
}

(function() {
    var oldtest = test;
    test = function() {
        oldtest();
        console.log("2");
    }
}())

(function() {
    var oldtest = test;
    test = function() {
        oldtest();
        console.log("3");
    }
}())

Which is probably the simplest solution to my question - but not necessarily the best system to use (as it's dependant on the author to remember to callback the code - a dodgy module would break everything)

The Module Pattern is what you need.

In particular the 'Augmentation' or 'Loose Augmentation' patterns :

var MODULE = (function (my) {
    var old_moduleMethod = my.moduleMethod;

    my.moduleMethod = function () {
        // method override, has access to old through old_moduleMethod...
    };

    return my;
}(MODULE || {}));

You could make a function like this

function extendFunction(fn, pre, post) {
    return function () {
        var arg = arguments;
        if (pre) arg = pre.apply(this, arg);   // call pre with arguments
        arg = fn.apply(this, arg);             // call fn with return of pre
        if (post) arg = post.apply(this, arg); // call post with return of fn
        return arg;
    };
}

then extend as follows

var test = function () { // the master function
    console.log("1");
};
test = extendFunction(
    test, // function to extend
    null, // thing to do first
    function() {console.log("2");} // thing to do after
);
test = extendFunction(
    test,
    null,
    function() {console.log("3");}
);
test(); // 1, 2, 3

This is very different to the normal meaning of "extend" though, where you give new properties to Objects or set up prototype chains, and to "module" which normally involves wrapping all your code in a function expression so that you don't pollute the namespace.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM