我需要使用new Function()
构造函数创建一个具有可变数量参数的函数。像这样:
args = ['a', 'b'];
body = 'return(a + b);';
myFunc = new Function(args, body);
是否可以在没有eval()
的情况下执行此操作?
非常感谢,伙计们!实际上,a + b不是我主要关注的问题。我正在研究一个处理和扩展模板的代码,我需要将未知(和变量)数量的参数传递给函数,以便将它们作为局部变量引入。
例如,如果模板包含:
<span> =a </span>
我需要输出参数a
的值。也就是说,如果用户声明扩展功能为
var expand = tplCompile('template', a, b, c)
然后调用
expand(4, 2, 1)
我需要用=a
替换4
。是的,我很清楚,功能类似于eval()
并且运行速度非常慢,但我没有其他选择。
答案 0 :(得分:45)
您可以使用apply()执行此操作:
args = ['a', 'b', 'return(a + b);'];
myFunc = Function.apply(null, args);
如果没有new
运算符,Function
会得到完全相同的结果。您可以使用push(),unshift()或splice()等数组函数修改数组,然后再将其传递给应用。
您也可以将逗号分隔的参数字符串传递给 Function :
args = 'a, b';
body = 'return(a + b);';
myFunc = new Function(args, body);
在旁注中,您是否知道arguments对象?它允许您使用数组样式括号表示法获取传递给函数的所有参数:
myFunc = function () {
var total = 0;
for (var i=0; i < arguments.length; i++)
total += arguments[i];
return total;
}
myFunc(a, b);
这比使用 Function 构造函数更有效,并且可能是实现所需内容的更合适的方法。
答案 1 :(得分:7)
@ AndyE的回答是正确的如果,构造函数不关心您是否使用new
关键字。有些功能并不宽容。
如果您发现自己处于需要使用new
关键字的情况,并且需要向函数发送可变数量的参数,则可以使用此
function Foo() {
this.numbers = [].slice.apply(arguments);
};
var args = [1,2,3,4,5]; // however many you want
var f = Object.create(Foo.prototype);
Foo.apply(f, args);
f.numbers; // [1,2,3,4,5]
f instanceof Foo; // true
f.constructor.name; // "Foo"
ES6及更高版本!
// yup, that easy
function Foo (...numbers) {
this.numbers = numbers
}
// use Reflect.construct to call Foo constructor
const f =
Reflect.construct (Foo, [1, 2, 3, 4, 5])
// everything else works
console.log (f.numbers) // [1,2,3,4,5]
console.log (f instanceof Foo) // true
console.log (f.constructor.name) // "Foo"
答案 2 :(得分:2)
您可以这样做:
let args = '...args'
let body = 'let [a, b] = args;return a + b'
myFunc = new Function(args, body);
console.log(myFunc(1, 2)) //3
答案 3 :(得分:0)
如果您只是想要一个sum(...)
功能:
function sum(list) {
var total = 0, nums;
if (arguments.length === 1 && list instanceof Array) {
nums = list;
} else {
nums = arguments;
}
for (var i=0; i < nums.length; i++) {
total += nums[i];
}
return total;
}
然后,
sum() === 0;
sum(1) === 1;
sum([1, 2]) === 3;
sum(1, 2, 3) === 6;
sum([-17, 93, 2, -841]) === -763;
如果您想要更多,请提供更多详细信息?如果你不知道自己要做什么,就很难说你怎么做。
答案 4 :(得分:0)
有几种不同的方法可以写出来。
// assign normally
var ab = ['a','b'].join('');
alert(ab);
// assign with anonymous self-evaluating function
var cd = (function(c) {return c.join("");})(['c','d']);
alert(cd);
// assign with function declaration
function efFunc(c){return c.join("");}
var efArray = ['e','f'];
var ef = efFunc(efArray);
alert(ef);
// assign with function by name
var doFunc = function(a,b) {return window[b](a);}
var ghArray = ['g','h'];
var ghFunc = function(c){return c.join("");}
var gh = doFunc(ghArray,'ghFunc');
alert(gh);
// assign with Class and lookup table
var Function_ = function(a,b) {
this.val = '';
this.body = b.substr(0,b.indexOf('('));
this.args = b.substr(b.indexOf('(')+1,b.lastIndexOf(')')-b.indexOf('(')-1);
switch (this.body) {
case "return":
switch (this.args) {
case "a + b": this.val = a.join(''); break;
}
break;
}
}
var args = ['i', 'j'];
var body = 'return(a + b);';
var ij = new Function_(args, body);
alert(ij.val);
答案 5 :(得分:0)
ES5中引入的新功能是reduce
数组方法。 You can use it to sum numbers, and it is possible to use the feature in older browsers with some compatibility code.
答案 6 :(得分:-1)
new Function(...)
以这种方式声明功能会导致 该函数不被编译,和 可能比另一个慢 宣布职能的方式。
让我们用JSLitmus 检查它并运行一个小的测试脚本:
<script src="JSLitmus.js"></script>
<script>
JSLitmus.test("new Function ... ", function() {
return new Function("for(var i=0; i<100; i++) {}");
});
JSLitmus.test("function() ...", function() {
return (function() { for(var i=0; i<100; i++) {} });
});
</script>
我上面做的是创建一个function expression
和function constructor
执行相同的操作。结果如下:
FireFox效果结果
IE效果
根据事实,我建议使用function expression
代替function constructor
var a = function() {
var result = 0;
for(var index=0; index < arguments.length; index++) {
result += arguments[index];
}
return result;
}
alert(a(1,3));
答案 7 :(得分:-1)
function construct(){
this.subFunction=function(a,b){
...
}
}
var globalVar=new construct();
VS
var globalVar=new function (){
this.subFunction=function(a,b){
...
}
}
如果有子功能,我更喜欢第二个版本。
答案 8 :(得分:-1)
答案 9 :(得分:-1)
在此示例中,我使用了lodash:
function _evalExp(exp, scope) {
const k = [null].concat(_.keys(scope));
k.push('return '+exp);
const args = _.map(_.keys(scope), function(a) {return scope[a];});
const func = new (Function.prototype.bind.apply(Function, k));
return func.apply(func, args);
}
_evalExp('a+b+c', {a:10, b:20, c:30});