0

I have code like this

var e = new window[className](...);

where

className

is a name of some "class" I've created and is specified in an attribute in my html. All I had to do was make sure I had loaded a constructor/function of the name in className and it worked.

I've started getting all my stuff into require and this has unsurprisingly stopped working. I have a file Eric.js which I have required, and contains

define('Eric',function(){
var Eric = function (ED) {
...
};
// etc

return Eric;
});

but

require(['wtt/Eric']);
className='Eric';
var e = new window[className](...);

produces

TypeError: window[className] is not a constructor
Mark Lester
  • 363
  • 4
  • 13
  • 1
    You should post more of your code, any error messages you get and things you have tried to do in order to resolve this. – ekuusela Apr 16 '15 at 18:07
  • I've included a sketch f what I am requiring. Hope that makes my problem clearer. – Mark Lester Apr 16 '15 at 22:42
  • I'm not sure but I think you will find answer [there](http://stackoverflow.com/questions/4869530/requirejs-how-to-define-modules-that-contain-a-single-class). – Terry Sahaidak Apr 16 '15 at 22:48

2 Answers2

1

Typical usage of requirejs is:

require(['wtt/Eric'], function(Eric) {
    var e = new Eric(...);
});

Is it possible for you to use require in that way?

P.S. By the way, you should avoid usage of global vars in your code and add small fix to Eric module definition:

define('Eric', function() {
    var Eric = function (ED) { // <- here comes the "var" keyword
        // ...
    };
    // etc

    return Eric;
});

You can read more let's say here: http://www.w3.org/wiki/JavaScript_best_practices#Avoid_globals

Vladimir Posvistelik
  • 3,843
  • 24
  • 28
  • thanks. I'll fix my globals. my problem is I dont know what 'Eric' is going to be, it might be MapEric or some other sub class I have cooked up. I will read this name in from the HTML, i.e. it's an attribute value in a div tag. I can just build a switch table, but I like being able to go "run the function of this name". I've looked at window[] and it doesnt seem to have my "required" stuff. – Mark Lester Apr 17 '15 at 06:39
1

You seem to be unaware that RequireJS operates asynchronously. Let's look at your code:

require(['wtt/Eric']);
className='Eric';
var e = new window[className](...);

The first line (require...) will cause RequireJS to initiate loading your module. You do not actually know when the module will be loaded. In fact, given the way JavaScript works, you are guaranteed that by the time var e = new window[className](...); executes, your module will not be loaded and this line will fail. So you have to structure you code so that the line which fails is guaranteed to run after the module is loaded. You do this by passing a callback to require:

require(['wtt/Eric'], function () {
    var e = new window['Eric'](...);
    ...
});

Or even better, don't leak anything in the global space and do:

require(['wtt/Eric'], function (Eric) {
    var e = new Eric();
    ...
});

Regarding the comment you left on the other answer, note that it is possible to compute what module to load at run time:

var mod = document.getElementById("myid").attributes.foo.value;
require(['wtt/' + mod], function (Constructor) {
    var e = new Constructor();
});

If you ever use r.js to combine your modules, you'll have to explicitly list the modules you load in the manner I've just shown above because r.js is not able to follow computed dependencies.

Louis
  • 146,715
  • 28
  • 274
  • 320
  • Yes, I just twigged the asynchronous issue. Moreover, I have also now come into contact with backbone and underscore. So what was a few days packaging has turned into a major overhaul. We arent getting any nearer to how I might go var thing= new window[$name](); – Mark Lester Apr 17 '15 at 11:45
  • You've answered the question. But you've told me off for polluting the global namespace. But I still want the constructor name to be a variable, it's read from the document. I guess I can go lookup['Eric']=Eric; new lookup[className]() – Mark Lester Apr 19 '15 at 13:27