How do I access module variables using requireJS?
Asked Answered
S

2

10

I have been using Javascript for a while and I have just tried using modules and requireJS for the first time and its hard to get my head around new design patterns!

Here is my first attempt:

require([
    "jquery",
    "testModule"
], function ($, testModule) {
    $(function () {
        var testInstance1 = testModule;
        testInstance1.setID(11);
        alert(testInstance1.id);
    });
});

and testModule.js

define([
  'jquery'
], function ($) {

    var id = 0;

    var setID = function (newID) {
        id = newID;
        return id;
    };
    return {
        setID: setID,
        id:id
    };
});

This returns 0 and I was expecting 11. What am I missing?

It is also a simplified example of course. I would like to create multiple objects and each should keep its own variables in state. For example if I wanted a module to append a list to a container DIV but also contain functions to add, clear or query data in that list how should I structure the module functions so that each implementation keeps its own state.

Thanks

Saks answered 16/9, 2012 at 19:10 Comment(0)
G
6

You actually aren't missing anything requireJS related here. The problem is that only objects are passed around by reference (and maybe arrays.. can't remember for sure right now). Numbers are not. So, when you returned {setID: setID, id: id}, the 'id' got set to the value of 'id', never again to be updated. What you want to do is use a function such as 'getID', which will reference the original variable, rather than the original variable's value:

return {
    setID: setID,
    getID: function () {return id;}
};

and then...

testInstance1.setID(11);
alert(testInstance1.getID());
Geriatrician answered 16/9, 2012 at 19:45 Comment(3)
Thanks for your help. This works until I try to create 2 instances. 'var testInstance1 = testModule; testInstance1.setID(11); var testInstance2 = testModule; testInstance2.setID(99); alert(testInstance2.getID()); alert(testInstance1.getID());' Both give 99.Saks
Well, you're changing the same variable.. you probably need a more complex structure than the one that you've got, such as having a 'testModule.createInstance()'Geriatrician
Stephen, your answer helped me really get RequireJS modules. I can't thank you enough.Agrarian
T
3

If you want to have two instances of testModule you'll need to return testModule as a function. Then when you require it you can instantiate multiple instances using new.

Example 1

testModule.js

define([
  'jquery'
], function ($) {

    function TestModule() {
        var self = this;
        // anything attached to self or this will be public
        self.id = 0;
        self.setID = function (newID) {
            self.id = newID;
            return self.id;
        };
    }

    return TestModule;
});

main.js

require([
    "jquery",
    "testModule"
], function ($, TestModule) {
    $(function () {
        var testInstance1 = new TestModule();
        var testInstance2 = new TestModule();
        testInstance1.setID(11);
        testInstance2.setID(99);
        alert(testInstance1.id); // Should return 11
        alert(testInstance2.id); // Should return 99
    });
});

Or if you want to get fancy, you can protect certain properties or functions within testModule.

Example 2

testModule.js

define([
  'jquery'
], function ($) {

    function TestModule() {
        var self = this;
        var privateID = 0;
        function privateToString() {
            return 'Your id is ' + privateID;
        }
        // anything attached to self or this will be public
        self.setID = function (newID) {
            privateID = newID;
        };
        self.getID = function () {
            return privateID;
        };
        self.toString = function () {
            return privateToString();
        };
    }

    return TestModule;
});

main.js

    require([
        "jquery",
        "testModule"
    ], function ($, TestModule) {
        $(function () {
            var testInstance1 = new TestModule();
            var testInstance2 = new TestModule();
            testInstance1.setID(11);
            testInstance2.setID(99);
            alert(testInstance1.getID()); // Should return 11
            alert(testInstance2.getID()); // Should return 99
            alert(testInstance1.privateID); // Undefined
            alert(testInstance1.toString()); // Should return "Your id is 11"
        });
    });

If you just want a single instance like a singleton you can return TestModule using the new keyword.

Example 3

testModule.js

define([
  'jquery'
], function ($) {

    function TestModule() {
        var self = this;
        // anything attached to self or this will be public
        self.id = 0;
        self.setID = function (newID) {
            self.id = newID;
            return self.id;
        };
    }

    return new TestModule();
});

main.js

require([
    "jquery",
    "testModule"
], function ($, testModule) {
    $(function () {
        var testInstance1 = testModule;
        var testInstance2 = testModule;
        testInstance1.setID(11);
        testInstance2.setID(99);
        alert(testInstance1.id); // Should return 99
        alert(testInstance2.id); // Should return 99
    });
});
Toothsome answered 19/9, 2013 at 7:34 Comment(1)
Fantastic, This really opened my eyes for RequireJS. I am confortable with NodeJS modules being OO, but I needed to see this in RequireJS. Thank you.Vashtee

© 2022 - 2024 — McMap. All rights reserved.