有没有一种用 javascript 从字符串创建函数的方法?

例如:

var s = "function test(){
alert(1);
}";


var fnc = aMethod(s);

如果这是字符串,我想要一个函数,叫做 fnc。和 fnc();弹出警报屏幕。

eval("alert(1);")解决不了我的问题。

96401 次浏览

你已经很接近了。

//Create string representation of function
var s = "function test(){  alert(1); }";


//"Register" the function
eval(s);


//Call the function
test();

这是 工作用的小提琴

从字符串创建函数的更好方法是使用 Function:

var fn = Function("alert('hello there')");
fn();

这样做的优缺点是,当前范围(如果不是全局的话)中的变量不适用于新构造的函数。

传递观点也是可能的:

var addition = Function("a", "b", "return a + b;");
alert(addition(5, 3)); // shows '8'

JavaScript中的动态函数名

使用 Function

var name = "foo";
// Implement it
var func = new Function("return function " + name + "(){ alert('hi there!'); };")();
// Test it
func();
// Next is TRUE
func.name === 'foo'

资料来源: http://marcosc.com/2012/03/dynamic-function-names-in-javascript/

使用 eval

var name = "foo";
// Implement it
eval("function " + name + "() { alert('Foo'); };");
// Test it
foo();
// Next is TRUE
foo.name === 'foo'

使用 sjsClass

Https://github.com/reduardo7/sjsclass

例子

Class.extend('newClassName', {
__constructor: function() {
// ...
}
});


var x = new newClassName();
// Next is TRUE
newClassName.name === 'newClassName'

是的,使用 Function是一个很好的解决方案,但是我们可以更进一步,准备通用解析器,解析字符串并将其转换为真正的 JavaScript 函数..。

if (typeof String.prototype.parseFunction != 'function') {
String.prototype.parseFunction = function () {
var funcReg = /function *\(([^()]*)\)[ \n\t]*{(.*)}/gmi;
var match = funcReg.exec(this.replace(/\n/g, ' '));


if(match) {
return new Function(match[1].split(','), match[2]);
}


return null;
};
}

使用例子:

var func = 'function (a, b) { return a + b; }'.parseFunction();
alert(func(3,4));


func = 'function (a, b) { alert("Hello from function initiated from string!"); }'.parseFunction();
func();

这里是 jsfiddle

我为从 string 创建函数的4种不同方法添加了一个 jsperf 测试:

  • 在函数类中使用 RegExp

    var func = "function (a, b) { return a + b; }".parseFunction();

  • 在“ return”中使用函数类

    var func = new Function("return " + "function (a, b) { return a + b; }")();

  • 使用官方函数构造函数

    var func = new Function("a", "b", "return a + b;");

  • 利用伊瓦尔

    eval("var func = function (a, b) { return a + b; };");

Http://jsben.ch/d2xtg

2个结果样本: enter image description here enter image description here

这种技术可能最终等同于 eval 方法,但是我想添加它,因为它可能对某些人有用。

var newCode = document.createElement("script");


newCode.text = "function newFun( a, b ) { return a + b; }";


document.body.appendChild( newCode );

这在功能上类似于在文档末尾添加 < script > 元素,例如:

...


<script type="text/javascript">
function newFun( a, b ) { return a + b; }
</script>


</body>
</html>

一个动态参数的例子:

let args = {a:1, b:2}
, fnString = 'return a + b;';


let fn = Function.apply(Function, Object.keys(args).concat(fnString));


let result = fn.apply(fn, Object.keys(args).map(key=>args[key]))

使用带有返回值的 new Function()并立即执行它。

var s = `function test(){
alert(1);
}`;


var new_fn = new Function("return " + s)()
console.log(new_fn)
new_fn()

如果您有一个字符串形式的函数表达式,并希望将其设置为函数,那么需要在传递给 new Function的字符串中包含 return 语句。

const strFn = "const sum = (a, b) => a + b"


const newFn = new Function(`${strFn}; return sum`)();


console.log(newFn(2, 3)) // 5

如果不立即执行,可以使用 function.call方法执行。记住它接受的第一个参数是 this

const newFn = new Function('const arrMultiplier = (arr) => arr.map(num => num * 2); return arrMultiplier')
console.log(newFn.call({}).call({}, [6, 4, 1, 0])); // [12, 8, 2, 0]