将JavaScript函数对象作为字符串从其名称中获取?
在JavaScript中,如果变量中有一个字符串,是否有方法获取对具有匹配名称的函数对象的引用?请注意,jQuery对我是可用的,因此我也可以使用它的任何助手方法 例如:将JavaScript函数对象作为字符串从其名称中获取?,javascript,Javascript,在JavaScript中,如果变量中有一个字符串,是否有方法获取对具有匹配名称的函数对象的引用?请注意,jQuery对我是可用的,因此我也可以使用它的任何助手方法 例如: myFunction = function(){}; var func_name = "myFunction"; var myFunctionPtr = ??? //how to get the function from the name 如果您知道这是一个可以使用的全局函数,请感谢: var functPtr = w
myFunction = function(){};
var func_name = "myFunction";
var myFunctionPtr = ??? //how to get the function from the name
如果您知道这是一个可以使用的全局函数,请感谢:
var functPtr = window[func_name];
//functPtr()
否则,将窗口替换为包含函数的父对象。此[func_name]应为您提供函数
var myfunc = this[func_name];
myfunc();
使用eval:
myFunction = function(){};
var func_name = "myFunction";
var myFunctionPtr = eval(func_name);
我刚刚在Firebug中做了一个快速测试,通过简单地
eval()
ing名称,我就可以从名称中获取函数。。。使用eval()
我感觉很脏,但它似乎很好地完成了这里的工作
var myFunctionPtr = eval(func_name);
一种安全的方法是在测试其类型时对声称的函数进行沙箱处理:
function isFunction(expr) {
function sandboxTemplate() {
var window, document, alert; // etc.
try {
return typeof $expr$ == "function";
} catch (e) {
return false;
}
}
try {
var sandbox = new Function(
sandboxTemplate.toString().replace("$expr$", expr)
+ "return sandboxTemplate()");
return sandbox();
} catch (e) {
return false;
}
}
function test(expr) {
document.write("<div>\"" + expr + "\" <b>is "
+ (isFunction(expr) ? "" : "not ")
+ "</b>a function</div>");
}
/* Let's do some testing */
function realFunction() {
}
test("realFunction"); // exists!
test("notHere"); // non-existent
test("alert('Malicious')"); // attempt to execute malicious code!
test("syntax error {"); // attempt to blow us up!
函数是函数(expr){
函数sandboxTemplate(){
变量窗口、文档、警报;//等。
试一试{
返回类型$expr$==“函数”;
}捕获(e){
返回false;
}
}
试一试{
var sandbox=新函数(
sandboxTemplate.toString().replace(“$expr$”,expr)
+“返回sandboxTemplate()”;
返回沙盒();
}捕获(e){
返回false;
}
}
功能测试(expr){
document.write(“\”+expr+“\”是“
+(isFunction(expr)?“”:“not”)
+“职能”);
}
/*让我们做一些测试*/
函数realFunction(){
}
测试(“realFunction”);//存在!
测试(“无”);//不存在
测试(“警报(‘恶意’)”);//试图执行恶意代码!
test(“语法错误{”);//试图炸毁我们!
输出:
- “realFunction”是一个函数
- “notHere”不是一个函数
- “警报(‘恶意’)”不是功能
- “语法错误{”不是函数
哦,这在不使用
eval
的情况下很好地实现了这一点——尽管有人可能会说,使用函数构造函数与eval
没有什么不同,但这从来都不是首选的方法。与其将函数名保留在func\u name
中,不如在某些情况下成功地保留对函数的引用ng类似于函数调用
如果您绝对需要将函数引用保持为字符串,则通常会使用哈希表将任意名称映射到变量(JS具有一流的函数,这使其成为可能)
(我不知道为什么,这是一个如此微小的脚本:)
有人建议您使用eval(func_name)
——但是由于JS的作用域,这可能很快就会失控
您还将您的
myFunction=function(){};
声明为全局变量。一方面,它允许您将其作为window[func\u name]
引用,但另一方面它污染了全局范围。找到了该函数,然后调用它们
autoCallBack : function(_action){
$(".module").each(function(){
var modulName = $(this).attr("id");
if( isFunction(modulName) ){
eval(modulName)();
}
});
}
isFunction : function(_functionName){
try {
eval(_functionName);
} catch (error) {
return false;
}
return true;
}
这取决于函数的声明位置和方式
如果它是全局的,而不是通过let name=…
或const name=…
语法声明的(并且它不是使用class
声明的类构造函数),则可以通过在全局对象上查找它作为属性来进行检查。(这些警告都是ES2015的内容;下面将详细介绍。)您可以在全局范围内的松散模式下通过this
获取对全局对象的引用;浏览器还为您提供了一个称为窗口的全局对象。因此,假设浏览器:
if (typeof window[func_name] === "function") {
// ....
}
如果它可能不是全局的,而只是在范围内,因为您的代码关闭了它,或者如果它是使用我提到的ES2015机制之一创建的,那么除了eval
,实在没有什么好的检查方法:
if (eval("typeof " + func_name) === "function") {
// ....
}
使用eval
是最后的手段,你必须只在严格控制输入的情况下使用它。但是当你不得不这样做,并且你有严格控制的输入时,这是可以的
关于ES2015的注意事项:
新的let
、const
和class
是非常有趣的beasties:在全局范围内使用时,它们创建全局对象,但不在全局对象上创建属性。截至ES2015,尽管全局对象的所有属性都是全局对象,但并非所有全局对象都是全局对象的属性。它都是全局对象的一部分试图控制严重污染的全局名称空间,并为JavaScript绑定模型带来更大的安全性(现在我们有了真正的模块)
因此(请注意,这将仅在最先进的浏览器中运行):
//全局范围,在浏览器中(因为我使用了'window'和'document.body'),它
//实现ES2015的这一方面(在我写这篇文章时,Firefox的SpiderMonkey
//没有,Chrome的V8在最新的Chrome上有;除了SpiderMonkey和IE
//快速赶上(没有测试IE Edge,可能它已经存在)
//此行为不需要严格模式,但目前仅限于V8
//在严格模式下支持块范围的构造。
“严格使用”;
设tbody=setup();
//老式var:在全局对象上创建属性,因此
//我们得到“函数,函数”
var f1=function(){/*…*/};
结果(“var声明”、类型f1、类型窗口[“f1”]);
//函数声明:在全局对象上创建属性,因此
//“功能,功能”
函数f2(){}
结果(“函数声明”、类型f2、类型窗口[“f2”]);
//`let`声明:不在全局对象上创建属性,因此
//函数,未定义
设f3=function(){/*…*/};
结果(“let声明”、类型f3、类型窗口[“f3”]);
//`const`声明:不在全局对象上创建属性,因此
//函数,未定义
常量f4=函数(){/*…*/};
结果(“常量声明”,类型为f4,类型为窗口[“f4”]);
//“阶级
if (eval("typeof " + func_name) === "function") {
// ....
}
// functions.js
var funcOne = function(){
console.log('function ONE called')
}
module.exports={
// name_exported : internal_name
funcOne : funcOne
}
// index.js
var methods = require('./functions.js') // path to functions.js
methods['funcOne']()
> node index.js
> function ONE called