55

How can I hook up an event to a function name I have defined as a string?

I'm using Prototype.js, although this is not Prototype-speficic.

$(inputId).observe('click', formData.fields[x].onclick);

This would result in JavaScript complaining that my handler is not a function. I would prefer not us use eval().

Diodeus - James MacFarlane
  • 112,730
  • 33
  • 157
  • 176
  • possible duplicate of [How to execute a JavaScript function when I have its name as a string](http://stackoverflow.com/questions/359788/how-to-execute-a-javascript-function-when-i-have-its-name-as-a-string) – oHo Nov 08 '13 at 10:15

10 Answers10

92

Property accessors can be used to access any object's properties or functions.

If the function is in the global scope, you can get it using the window object:

var myFunc = window[myFuncName];

This also works within the this scope:

var myFunc = this[myFuncName];
Ryenski
  • 9,582
  • 3
  • 43
  • 47
Greg
  • 316,276
  • 54
  • 369
  • 333
9

I have worked on this problem, as I needed a function like this. Here is my sandbox code, not thoroughly tested, but can be a startpoint for others. Note that there is one eval() in the code as I couldn't figure out how to bypass that step, maybe a javascript quirk and cannot be done in any other way. Let me know if there is a way to get rid of eval() here!

executeFunctionByName = function(functionName)
{
    var args = Array.prototype.slice.call(arguments).splice(1);
    //debug
    console.log('args:', args);

    var namespaces = functionName.split(".");
    //debug
    console.log('namespaces:', namespaces);

    var func = namespaces.pop();
    //debug
    console.log('func:', func);

    ns = namespaces.join('.');
    //debug
    console.log('namespace:', ns);

    if(ns == '')
    {
        ns = 'window';
    }

    ns = eval(ns);
    //debug
    console.log('evaled namespace:', ns);

    return ns[func].apply(ns, args);
}


core = {
    paragraph: {
        titlebar: {
            user: "ddd",
            getUser: function(name)
            {
                this.user = name;
                return this.user;
            }
        }
    }
}

var testf = function()
{
    alert('dkdkdkd');
}

var x = executeFunctionByName('core.paragraph.titlebar.getUser', 'Ikon');
executeFunctionByName('testf');
Ikon
  • 661
  • 8
  • 14
8

... or this[myFuncName];

dkretz
  • 37,399
  • 13
  • 80
  • 138
6

Perhaps?

setTimeout ( "myFunc()", 1 );
Anthony Scaife
  • 564
  • 5
  • 15
5

Just an eval would do the job

var call = eval("method_name").call(args);
Devraj Gadhavi
  • 3,541
  • 3
  • 38
  • 67
3
window.myFunction === window["myFunction"]
yojimbo87
  • 65,684
  • 25
  • 123
  • 131
geowa4
  • 40,390
  • 17
  • 88
  • 107
3

Looks like formData.fields[x].onclick holds the name of a global function? If so try:

$(inputId).observe('click', window[formData.fields[x].onclick]);
Crescent Fresh
  • 115,249
  • 25
  • 154
  • 140
1

Do you know what the onclick property contains or what type it is? I assume this is prototype specific stuff, as "fields" does not exist in DOM forms.

Thomas Kjørnes
  • 1,928
  • 1
  • 17
  • 17
0

If you need to call a string function with arguments, do this:

window[stringFunctionName].apply( window, arrayOfArguments )

You can use scope in place of window if preferred

cronoklee
  • 6,482
  • 9
  • 52
  • 80
0

update:--- use ES6 export and import

a.js

const fn = {
  aaa: function() {
    //code
  },
  bbb: function() {
    //code
  },
  //codes ....
  nnn: function() {
    //code
  }
}

export default fn

b.js

  import someFn from './a'
  //eg
  const str1='aaa'
  const str2 = 'bbb'

  someFn[str1]()

These methods above always not be recommend by some reasons, but they are really convenient to use. These methods below are safe, but really not conveninet to use.

  • switch...case (or if...else)

    switch(str){
        case 'str1': 
            fn1()
            break
        case 'str2':
            fn2
            //and so on
    }
    
  • put functions in a object

    const fn={
        str1:fn1,
        str2:fn2
        //and so on
    }
    fn[str1] //call function
    
levinit
  • 394
  • 3
  • 7