11

How do I create a new object in javascript based on a variable type-string (containing the name of the object)?

Now I have: (with more tools coming the list will get longer...)

function getTool(name){
  switch(name){
    case "SelectTool":
      return new SelectTool();
      break;
    case "LineTool":
      return new LineTool();
      break;
    case "BlurTool":
      return new BlurTool();
      break;
    case "PointerTool":
    default:
      return new PointerTool();
      break;
  }
}

And defined my tools like:

PointerTool.prototype = new Tool;
PointerTool.prototype.constructor = PointerTool;
function PointerTool(){
  this.name = "PointerTool";
}
PointerTool.prototype.click = function(x, y){
  info("You clicked at: "+x+", "+y);
}

I would like to get ride of the (growing) switch statement, it seems 'wrong'.

13
  • Hypothetically, eval could do it ... Commented Dec 5, 2010 at 19:30
  • 2
    @Šime Vidas, but practically, eval should be avoided at all costs :D Commented Dec 5, 2010 at 19:32
  • @Gabi, I agree that eval() is not the correct solution here, but I'm curious why you assert that "eval should be avoided at all costs". It is a non-deprecated feature of the language, with appropriate (and inappropriate) uses -- just like every other feature. Commented Dec 5, 2010 at 19:46
  • @Šime: I'll ask Jeff to add downvotes on comments! :-P Commented Dec 5, 2010 at 19:47
  • 2
    Sometimes eval is the only answer, and that is when it should be used. If these objects were defined within an anonymous self executing function, they could not be referenced using window[constructor]. Commented Dec 5, 2010 at 20:03

3 Answers 3

19
function getTool(name){
  return ( typeof window[name] === 'function' ) ? 
                                    new window[name]() : {/*some default*/};
}

Assumes PointerTool constructor is defined in the global window namespace. Replace that with whatever namespace you're using.

Sign up to request clarification or add additional context in comments.

3 Comments

If you're using Node.js you can use the GLOBAL object to do this same thing.
I'll go with this solution for now, totaly forgot that everything is a function, thus also the global window object/functions/namespace :)
@Dribbel - Sounds good. I only used window because I wasn't certain of the namespace. I'd recommend defining them in some other namespace if you are using window. The same technique can be used, but if getTool isn't doing anything else, you could eliminate that function call.
8

You should consider rethinking your approach. It would be better to have something like a Tools object, which would have the tools as properties, like

Tools = {"SelectTool": SelectTool /* etc */}`.

This way, you could access the tools both as new Tools.SelectTool and new Tools[var_with_tool_name].

1 Comment

Yes, but it works even if the tools are in different namespaces.
3

In your example, you're declaring PointerTool as a function in the global scope. Assuming your javascript is running the browser, the "global scope" is actually the same as the window object. That means that if you have a constructor:

function PointerTool() {
   ...
}

that's the same as this:

window.PointerTool = function() {
   ...
}

So now, in your getTool function, you can access your constructor functions like this:

function getTool(name){
    return new window[name]();
}

A more "future proof" way to do this would be to do define your own namespace object, in which you'll place all your various tool constructors. Something like this ("myproject" would be the short name of your project or system):

var myproject = { tools: {} };

// Pointer Tool Constructor
myproject.tools.PointerTool = function() {
   ...
}

// Line Tool Constructor
myproject.tools.LineTool = function() {
   ...
}

// and so on

Then your getTool function would look like this:

function getTool(name){
    return new myproject.tools[name]();
}

This approach keeps your stuff isolated from whatever other stuff happens to be defined in the global/window scope.

2 Comments

No, function PointerToolwindow.PointerTool = function: the first is a function declaration, the second a function expression. kangax.github.com/nfe/#expr-vs-decl
True, but in the context of this question, it is equal enough. That is, you can reference PointerTool by using window.PointerTool, which is the point of this answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.