在 select 元素上分派,无需评估或复制粘贴
Dispatch on select element without eval or copy & paste
编辑:此问题与 "how do I call a javascript function when all I have is a string containing its name" 重复。 dom 互动让人分心。
我想在用户从 html select 元素中选择一个选项时调用 N 个不同的 javascript 函数之一。我想在不重复自己或退回到 eval() 的情况下执行此操作。
修改一个存储在选项值字段中的字符串,然后将它们用作字典中的索引。
<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>
修订版 2 将函数存储在值字段中并对其调用 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>
选项三是针对问题使用代码生成器,但这似乎是失败主义者。什么是明智的、惯用的解决方案?
这是一个小例子(可能需要针对不同的浏览器进行调整):
<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>
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>
编辑:此问题与 "how do I call a javascript function when all I have is a string containing its name" 重复。 dom 互动让人分心。
我想在用户从 html select 元素中选择一个选项时调用 N 个不同的 javascript 函数之一。我想在不重复自己或退回到 eval() 的情况下执行此操作。
修改一个存储在选项值字段中的字符串,然后将它们用作字典中的索引。
<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>
修订版 2 将函数存储在值字段中并对其调用 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>
选项三是针对问题使用代码生成器,但这似乎是失败主义者。什么是明智的、惯用的解决方案?
这是一个小例子(可能需要针对不同的浏览器进行调整):
<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>
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>