2014-03-13 141 views
3

运行功能我有这样的选择菜单:从属性字符串

HTML

<select name="moduleGroup"> 
    <option data-function="getListing('pages')">Pages</option> 
</select> 

的Javascript

function getListing(s) { 
    console.log(s); 
} 

$('select').on('change', function() { 
    var func = $(this).find('option:selected').attr('data-function'); 
    [func](); 
}); 

我也试过,$[func]();$('body')[func]();

我已阅读多个岗位大约同样的问题,但没有帮助我:herehere

我敢肯定,我做错了什么,但有人可以点我在正确的方向吗?

回答

1

非常简单的方法是调用eval()这样的:

$('select').change(function() { 
    var func = $(this).find('option:selected').attr('data-function'); 
    eval(func); 
}); 

小提琴:http://jsfiddle.net/gywzb/4/

但整个世界的认同,这是一个不好的做法。正如我最喜欢的linter所说,“eval()是邪恶的。”它会为你带来许多令人讨厌的安全漏洞(特别是当你维护应用程序,并且事情从你最初编写它的方式发生变化时),而且无论如何性能还是很糟糕。幸运的是,有一个更好的方法。

首先,我要打破你的数据属性一点点,这样的而不是包含函数名和参数的一个属性,你将有两个属性:一个函数名,而另一为参数。

<select name="moduleGroup"> 
    <option data-function="getListing" data-parameter="pages">Pages</option> 
</select> 

其次,我们将创建一个“类”,它包装的功能,如:

var MyClass = function() { 
} 

MyClass.prototype = { 
    getListing: function(s) { 
     console.log(s); 
    } 
}; 

最后,这里是你如何使用上面的改变调用函数:

$('select').on('change', function() { 
    var func = $(this).find('option:selected').attr('data-function'); 
    var param = $(this).find('option:selected').attr('data-parameter'); 

    var myInstance = new MyClass(); 
    var funcRef = myInstance[func]; 
    funcRef.call(myInstance, param); 
}); 

下面是一个小提琴整个事情:http://jsfiddle.net/7CwH4/2/

,奇迹发生了,你当我们请拨打.call method来调用您的功能。 .call()方法的第一个参数是该函数将作为其this对象看到的对象。 .call的下一个参数是该函数的第一个参数。 (如果你的功能了更多的参数,.call第三个参数是给函数的第二个参数等,为.callMDN documentation,如果这是令人困惑的。)

如果你需要传递比一个更复杂的数据字符串作为参数,你可以把它放在data-parameter属性作为一个JSON字符串,然后用$.parseJSON把它转换成一个对象参数传递给函数之前:

// If your data-parameter attribute contained a JSON string. 
$('select').on('change', function() { 
    var func = $(this).find('option:selected').attr('data-function'); 
    var param = $(this).find('option:selected').attr('data-parameter'); 

    var paramObj = $.parseJSON(param); 

    var myInstance = new MyClass(); 
    var funcRef = myInstance[func]; 
    funcRef.call(myInstance, paramObj); 
}); 
+0

哇三江源这个非常详细的答复!由于这不会构成任何威胁,因为它仅仅适用于我自己,这可以在'eval'上正常工作,但是再次感谢您! –

+1

实际上,执行“正确”方式的代码并不比使用“eval”执行代码复杂得多。你可以看看这些小提琴 - 如果我没有详细解释这些变化,你几乎不会注意到它们的区别。 (虽然当你有一个简单的解决方案,而其他问题也在呼叫时,我完全不想跳进这个问题的细节。) –