为何无法调用通过Function()构造函数创建的函数?
问题根源:字符串拼接的引号冲突导致语法错误
你遇到的问题核心是动态生成函数时的字符串引号冲突,导致最终创建的函数存在语法错误——虽然函数对象能正常生成(所以console.log(myFnc)能打印出函数),但调用时会因为语法问题无法正确执行,进而出现undefined或error的异常结果。
我们来拆解一下问题:
你的funcGenerator里拼接函数体的代码是:
"try{ return " + f + '; } catch (e) { return "error"; }'
当你传入'value.toLowerCase()'后,拼接出来的完整函数体字符串是:
try{ return value.toLowerCase(); } catch (e) { return "error"; }
注意这里的"error"用了双引号,而整个函数体字符串是用双引号包裹的!这会让JS解析器误以为return "之后的内容是字符串外的代码,直接造成语法错误。虽然new Function不会在创建函数对象时立刻抛出语法错误(JS函数是懒解析的),但调用函数时就会触发语法异常,甚至连catch块的代码都无法正常执行,最终返回undefined。
修复方案
最稳妥的方式是使用ES6模板字符串(反引号包裹),彻底避免引号冲突问题:
funcGenerator(f) { return new Function("value", `try { return ${f}; } catch (e) { return "error"; }`); }
模板字符串允许内部自由使用单引号和双引号,不会和外层的反引号产生冲突,能保证生成的函数体语法完全正确。
修复后再测试:
- 调用
myFnc('THIS to loWeR')会正确返回"this to lower" - 调用
myFnc()时,因为value为undefined调用toLowerCase()报错,会进入catch块返回"error"
另外提醒一句:使用new Function动态生成函数要注意安全风险,如果f的内容来自用户输入,可能存在代码注入的隐患,生产环境中要谨慎处理。
内容的提问来源于stack exchange,提问作者JohnW2Smith
相关产品推荐
相关产品推荐

