简体   繁体   中英

How can a Javascript module defined with AMD be extended?

First a bit of history, we have an engine which is made up of many javascript files which are essentially modules. These modules return a single class that are assigned to the global scope, although under a specified namespace.

The engine itself is used to display eLearning content, with each different eLearning course requiring slightly different needs, which is where we include javascript files into the page based on the necessary functionality. (There is only one entry page).

I've been trying to weigh up if it's worth changing to AMD, require.js and r.js or if it's better to stay with our current system which includes everything required on the page and minimises it into one script.

One of my biggest problems with going to AMD would be that it seems to be harder to extend a class easily. For example, sometimes we have to adjust the behaviour of the original class slightly. So we add another script include on the page that extends the original class by copying the original prototype, execute the original function that's being overridden with apply and then do whatever additional code is required.

Can you extend an AMD module without adapting the original file? Or am I missing the point and we're best staying with what we're doing at the moment?

I recently started a project using RequireJS, and the method I use to extend underscore boils down to something like this:

Relevant Directory Structure:

  • /scripts
  • /scripts/underscore.js
  • /scripts/base/underscore.js

The real underscore library goes to /scripts/base/underscore.js.

My extensions go in /scripts/underscore.js .

The code in /scripts/underscore.js looks like this:

define(['./base/underscore'], function (_) {
    'use strict';

    var exports = {};

    // add new underscore methods to exports

    _.mixin(exports); // underscore's method for adding methods to itself

    return _; // return the same object as returned from the underscore module
});

For a normal extension, it could look more like this:

define(['underscore', './base/SomeClass'], function (_, SomeClass) {
    'use strict';

    _.extend(SomeClass.prototype, {
        someMethod: function (someValue) {
            return this.somethingOrOther(someValue * 5);
        }
    });

    return SomeClass;
});

Note on underscore: Elsewhere I used the RequireJS shim-config to get underscore to load as an AMD module, but that should have no effect on this process with non-shimmed AMD modules.

You can have modules that contain your constructor functions. when these modules get included, they are ready for use. then you can create objects out of them afterwards.

example in require:

//construction.js
define(function(){

    //expose a constructor function
    return function(){
        this....
    }
});

//then in foo.js
define([construction],function(Construction){
    var newObj = new Construction;  //one object using constructor
});

//then in bar.js
define([construction],function(Construction){

    //play with Construction's prototype here then use it

    var newObj = new Construction;
});

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