How can a Javascript module defined with AMD be extended?
Asked Answered
C

2

8

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?

Clarhe answered 25/4, 2012 at 8:25 Comment(0)
O
6

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.

Osteomalacia answered 1/10, 2012 at 3:34 Comment(0)
C
0

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;
});
Christchurch answered 25/4, 2012 at 8:35 Comment(3)
Hi Joseph, thanks for your response but that's not the question I was asking. You're creating instances of the original constructor. I'd like to have a definition of say 'engine', which is used in a definition for another item, let's say 'contentScreen'. However between the definition of 'engine' and the creation of the 'contentScreen' I'd like to extend 'engine' slightly.Clarhe
@Clarhe what do you mean by "extending slightly"? building a modified constructor and then use that modified constructor? this might helpChristchurch
Essentially yes, I don't want to create a new class that extends the original, I actually want to extend the original and use it, because as far as everything else is concerned it's still the same class. As far as I can tell I can't do that with AMD?Clarhe

© 2022 - 2024 — McMap. All rights reserved.