最近有个这样的需求,要在我们的后台界面上,让平台使用者可以输入一段脚本,然后在nodejs层,读取这个脚本并执行。并且还要支持自定义输入参数的能力。 研究了一下Function的使用,记录在这里。
1 2 3 4 5 6 7 8 9 interface FunctionConstructor { new (...args : string[]): Function ; (...args : string[]): Function ; readonly prototype : Function ; }
使用new Function(functionScript)可以根据一个脚本字符串生成一个动态的函数。 然后执行这个函数即可得到函数的结果。
例如:
1 2 3 let functionScript = "return 1+2" let f = new Function (functionScript)();let result = f ();
result执行结果为3。 非常的简单。
复杂一点的也行,比如:
1 2 3 4 5 6 7 8 let functionScript = "if (1 > 2) {\n" + " return 1;\n" + "} else {\n" + " return 2;\n" + "}" let f = new Function (functionScript);let result = f ();
运行结果是2。
上面的都是不带参数的,带参数的也可以,比如下面这个函数:
1 2 3 4 5 6 7 function findMax (data1, data2 ) { if (data1 > data2) { return data1; } else { return data2; } }
它带有两个参数,data1和data2,这就需要传到Function里面。
1 2 3 4 5 6 7 8 let functionScript = "if (data1 > data2) {\n" + " return data1;\n" + "} else {\n" + " return data2;\n" + "}" let f = new Function ("data1" ,"data2" ,functionScript);let result = f (1 ,2 );
以上,就完成了脚本动态执行的功能。
另外,扩展运算符( spread )...args 在生成Function中经常使用。 扩展运算符能将一个数组转为用逗号分隔的参数序列。
1 2 console .log (...[1 , 2 , 3 ])console .log (1 , 2 , 3 )
上面这两行代码就是完全等价的。
Function 的构造函数 new(...args: string[]): Function; 的args参数,是需要展开的,不是一个数组。但是实际开发中,参数肯定是要用数组来保存的。这里就需要用扩展运算符来展开。
上面的代码,就可以转行成下面的形式。
1 2 3 4 5 6 7 8 9 10 11 let argsKey = ["data1" , "data2" ];let argsValue = [1 , 2 ];let functionScript = "if (data1 > data2) {\n" + " return data1;\n" + "} else {\n" + " return data2;\n" + "}" let f = new Function (...argsKey, functionScript);let result = f (...argsValue);