选择元素的调度,无需eval或copy&糊

时间:2015-07-21 21:35:44

标签: javascript html dry

编辑:这个问题与“我所拥有的是一个包含其名称的字符串时如何调用javascript函数”的重复。 dom互动是一种分心。

当用户从html select元素中选择一个选项时,我想调用N个不同的javascript函数之一。我想这样做而不重复自己或回归到eval()。

修订版1在选项的值字段中存储了字符串,然后将它们用作字典的索引。

<body>
<select onchange="dispatch(this)">
<option value="first_function_name">One</option>
<option value="second_function_name">Two</option>
</select>
</body>

<script>
function first_function() {console.log("There can be only one");}
function second_function() {console.log("Except when there are two");}
function dispatch(selection) {
  var name = selection.value;
  var lookup_table = {
    first_function_name: first_function,
    second_function_name: second_function
  };
  (lookup_table[name])();
}
</script>

Revision 2将函数存储在value字段中,并在其上调用eval。 Eval让我感到非常沉重。

<body>
<select onchange="dispatch(this)"> <!-- Not sure passing this is always OK -->
<option value="first_function()">One</option>
<option value="second_function()">Two</option>
</select>
</body>

<script>
function first_function() {console.log("There can be only one");}
function second_function() {console.log("Except when there are two");}
function dispatch(selection) {eval(selection.value);} /* yuck */
</script>

选项三是针对问题瞄准代码生成器,但这似乎是失败主义者。什么是理智的,惯用的解决方案?

2 个答案:

答案 0 :(得分:1)

这是一个小例子(可能必须针对不同的浏览器进行调整):

<select id="mySelect"></select>
<script type="text/javascript">
    (function() {

        var select = document.getElementById("mySelect");
        var options = [ { name: 'One', value:'one', callback: function() {console.log("There can be only one");}},
                        { name: 'Two', value:'two', callback: function() {console.log("Except when there are two");}}];
        options.forEach(
                    function(opt) {
                        var option = document.createElement("option");
                        option.text = opt.name;
                        option.value = opt.value;
                        select.add(option);
                    });
        function onChange() {
            options.some(function(option) {
                if (option.value===select.value) {
                    option.callback();
                    return true;
                }
            });
        }
        select.addEventListener("change", onChange);
    })();
</script>

答案 1 :(得分:1)

var closureObject = (function(){    // created scope
    /* so now "this" becomes the closureObject and which has all functions as property and
       can directly refer them by syntax Instance['propertyName'] */
    var closureObject = {};
    closureObject.first_function = function() {
          alert("There can be only one");
    }
    closureObject.second_function = function(){
          alert("Except when there are two");
    }
    return closureObject;
    })();

function dispatch(selection) {
          closureObject[selection](); // ClosureObject could be Global or scoped variable
}
<select onchange="dispatch(this.value)">
<option value="first_function">One</option>
<option value="second_function">Two</option>
</select>