Carl R
Carl R

Reputation: 8214

Map of functions in javascript?

I have a context menu that will trigger different javascript functions. The naive solution for choosing function looks like this:

function(action, el, pos) {
    switch(action)
    {
        case "export_selected_to_excel":
            exportSelectedToExcel(el);
            break;

        etc..
    }
}

I would like to have a map of functions instead, so that I can reduce the metod to something similar to this:

function(action, el, pos) {
    menuAction[action](el);
}

I define the array like this:

function exportSelectedToExcel(id){
   //stuff...
}

var menuAction = new Array();
menuAction["export_selected_to_excel"] = exportSelectedToExcel;

This seems to work fine and feels like a reasonable solution.

Are there any downsides to do like this in javascript?
Is there even better ways to do it?

Upvotes: 11

Views: 16300

Answers (4)

jeffreydev
jeffreydev

Reputation: 1722

if you do it like that the function will point to another function and thus create some overhead, you can also define the function directly inside of the object, so for example:

var menuAction = {};
menuAction.export_selected_to_excel = function (id) {
    // stuff
}

and to make sure a function exists you can do:

var action = 'export_selected_to_excel';
if(typeof menuAction[action] == 'function')
{
    // call function
}

Upvotes: 2

Jiri Kriz
Jiri Kriz

Reputation: 9292

Your idea is good, but you should not use Arrays as associative maps, because they are not associative (see e.g. Mastering Javascript Arrays). When you do var a = []; a["x"] = y you assign in fact the property x to the object a. So, it holds true afterwards: a.length == 0 and a.x == y.

You should just replace Array by object to get an associative map:

var menuAction = {};
menuAction["export_selected_to_excel"] = exportSelectedToExcel;
// or
menuAction.export_selected_to_excel = exportSelectedToExcel;
// or
menuAction.export_selected_to_excel = function(id) {...};

or:

var menuAction = {
    export_selected_to_excel: exportSelectedToExcel,
    export_x: exportX   // etc
}

Upvotes: 6

Cheeso
Cheeso

Reputation: 192457

if it is really the case that the names of the functions can be directly derived from the strings, eg,

export_selected_to_excel   => exportSelectedToExcel
compute_selected           => computeSelected
...

...then rather than using an associative array, you could dynamically generate the fn names and invoke them dynamically.

Use the answer to this question ( Convert hyphens to camel case (camelCase) ) to convert names.

Then, use the answer to this question ( How to execute a JavaScript function when I have its name as a string ) to invoke the function. Be sure to verify that window[functionName] is an actual function, with a typeof test.

Upvotes: 1

user278064
user278064

Reputation: 10170

I don't think there are big downsides. Indeed what you're trying to do is similar at what you do when you define an object and inside declare your functions.

e.g.:

var menuAction = {
    function action1(el) {
       // ...
    },
    function action2(el) {
       //...
    },

    // ...       
}

The only dfference is that in this case you're defining you're functions not in the object declaration but a-posteriori using the Associative Array notation.

Upvotes: 0

Related Questions