0

Possible Duplicate:
How to execute a JavaScript function when I have its name as a string

Struggling with this one, and I can't seem to find a good resource on it.

Background: I'm creating a step system, and I'm passing the direcition/order within an attribute data-step="1". This controls the ID that will be shown (that parts easy), but also the function that needs to be called in order to grab the correct information.

The question is basically, how can I call a function who's name I need to build dynamically?

IE: step1(); step2(); Except I want to dynamically ADD that number in there.

// In an essense, what I'm trying to achieve:
// It's always called step and then followed by a number

[step + directionNumber](); // which isn't working

Also trying to avoid using eval since we all know it's evil :)

Community
  • 1
  • 1
Mark Pieszak - Trilon.io
  • 61,391
  • 14
  • 82
  • 96

2 Answers2

3

Use

window["step" + directionNumber](); 

When you write in the global scope

function someName(){
}

you're defining a property of the global object (window) with name someName and value the function.

It's equivalent to

window.someName = function(){
}

So you can call your function as window.someName(); or, more useful here, as window['someName']();

A better solution would probably be to define an array of functions :

var stepFunctions = [];
stepFunctions[0] = function(){};

then you can call them using stepFunctions[directionNumber]();

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • Probably want to quote "step". – cHao Nov 28 '12 at 18:44
  • 2
    Also be warned, this will probably only work with global functions (which is what you'd find in `window`). For instance, `(function () { var x = function() { }; window["x"](); })() ` will typically throw a TypeError. – cHao Nov 28 '12 at 18:45
  • @SLaks Yes, I actually kept getting this, but didn't realize I hadn't been quoting `'step'`! This works perfectly.. You guys rule. – Mark Pieszak - Trilon.io Nov 28 '12 at 18:48
  • 1
    *"When you write `function someName(){}` you're defining a property of the global object."* This is *only* if the `function someName(){}` is declared in the global scope. – I Hate Lazy Nov 28 '12 at 18:49
  • @cHao You are spot on, it does only work with global(window) functions... is there anything I could add to make it work within a parent function perhaps also? (Just out of curiosity too) – Mark Pieszak - Trilon.io Nov 28 '12 at 18:49
  • @mcpDESIGNS: Can't think of anything for local variables. Even `eval` probably won't work there. For functions in some other object, though, you could refer to that object for them the same way you refer to `window` to access global stuff. Which is to say, if you want stuff to be accessible by name, stick it in an object somewhere. :) Then the name becomes a key, which is easy to work with dynamically. – cHao Nov 28 '12 at 18:53
  • @user1689607 yes... obviously... ^^ – Denys Séguret Nov 28 '12 at 19:02
  • Not necessarily obvious. I had a long battle with someone last week who refused to believe that `function foo(){}` wasn't equivalent to `foo = function(){}` *(no `var` declaration)*. – I Hate Lazy Nov 28 '12 at 19:09
  • ...and your updated answer still suggests that `function someName(){}` creates a property of `window` irrespective of where the declaration is located. Is this what you think? To be clear, `function someName(){}` is not necessarily equivalent to `window.someName = function(){}` – I Hate Lazy Nov 28 '12 at 19:13
  • *"Is this what you think?"* Please stop being offensive when you have a competive answer. You perfectly know we're just trying to make things clear for OP. – Denys Séguret Nov 28 '12 at 19:16
  • 1
    Either way it works like a charm, gave you +1 as well @user1689607 (how do you remember your username lol) I knew @dystroy was refering to the global scope with `function Whatever === window.Whatever`. – Mark Pieszak - Trilon.io Nov 28 '12 at 19:22
  • @dystroy: I have no idea why you would be offended. Your updated answer still doesn't correct this mistake, so it could be that you think that syntax creates a global irrespective if its location in code. It's simply wrong. If this offends you, I can't help that. And if you think answers are "competing", then I think you put far too much value on meaningless reputation points. – I Hate Lazy Nov 28 '12 at 19:23
  • Please read my answer instead of trying to see a mistake. – Denys Séguret Nov 28 '12 at 19:25
  • @mcpDESIGNS: Except that `function Whatever(){}` isn't necessarily equivalent to `window.Whatever = function(){}`. Variable scope plays a very real role. – I Hate Lazy Nov 28 '12 at 19:25
  • @user1689607 EVERYBODY knows it and nobody says otherwise. – Denys Séguret Nov 28 '12 at 19:27
  • @dystroy: Yes, I do see now that you had moved the wording around. You don't need to be so easily offended when you are corrected. You know that the wording started off being entirely incorrect, and it took a couple different edits for you to get it worded correctly. – I Hate Lazy Nov 28 '12 at 19:27
  • I find it fine when you precise something to OP or other readers because it might avoid a mistake and when you suggest to make it clearer. If find it offensive when you try to suggest, even after OP says he understood, that a seasoned javascript coder could have missed this basic point. – Denys Séguret Nov 28 '12 at 19:29
  • Yes, my comment to OP came after your final update, and I didn't see that you had the wording moved around in your last edit. So it seemed to be that OP was referring to the previous incorrect wording. This sort of confusion is what happens when there are multiple revisions to correct a mistake. – I Hate Lazy Nov 28 '12 at 19:41
1

Store your functions in an Object to dynamically access them by name.

var funcs = {};

funcs.step1 = function(){ console.log("foo"); };
funcs.step2 = function(){ console.log("bar"); };

var text = "step",
    number = 1;

funcs[text + number](); // foo

++number;

funcs[text + number](); // bar
I Hate Lazy
  • 47,415
  • 13
  • 86
  • 77
  • Yeah, I was thinking this as well - dystroy's answer certainly works and answers the question, but packing the functions into a separate object seems more sensible than throwing them into the window. – Bubbles Nov 28 '12 at 18:52