Javascript中能否在运行时创建函数?

4
维基百科关于一等公民的文章指出,“一些作者”认为,只有当语言支持在运行时创建函数时,函数才是该语言中的一等公民。詹姆斯·科格兰撰写的文章明确称函数是一等公民——无论他是否意识到有关一等公民标准的争议,我不知道。
以下是我的问题:
1. 使用“在运行时创建”这个额外标准,JavaScript程序是一等公民吗?
值得一提的是,基于更广泛的标准(适用于其他对象),JavaScript函数很明显是一等公民,即它们可以作为变量传递;因此,我觉得上述标准增加了一个有趣的动态或至少是一个澄清动态,而不像某个用户所写的那样“武断”。
  1. 如果是这样,JavaScript中运行时创建函数的过程是什么样子的(我们称之为promises、callbacks、anonymous等)?
  2. 如果不是,那么在其他语言中运行时创建函数的过程是什么样子的?

这个SO问题与你的问题非常相似。 - AWolf
@ColeJohnson,那其实从技术上讲并不正确。请阅读有关编程语言中一等公民函数争议的文章:http://programmers.stackexchange.com/questions/39742/when-is-a-feature-considered-a-first-class-citizen-in-a-programming-language-p(例如;互联网上还有更多相关内容)。 - Thomas
2个回答

14

可以使用Function构造函数动态创建函数。

var adder = new Function('a', 'b', 'return a + b');

adder(3, 4); // returns 7

更加详细地说,这可以用来应用任意二元运算符:

function make_binary_fun(operator) {
    return new Function('a', 'b', 'return a ' + operator ' b');
}
var adder = make_binary_fun('+');
var multiplier = make_binary_fun('*');

1
真实生活中很少使用True;Samuel Edwin Ward的答案中的示例更好,因为它通过日常JavaScript中使用的普通语言结构展示了函数是一等公民,而不是通过一个很少使用且相当邪恶的结构(出于与eval相同的原因)。 - Mark Amery
1
这个问题并不是完全清楚它的意思。那个答案是在创建相同函数的新闭包,而不是新函数。我认为这个问题不是关于实际使用中的内容,而只是关于语言设计和能力的一般性问题。 - Barmar
1
这是柯里化,技术上每次调用它都会创建一个新函数。不确定为什么这也不是一个有效的答案。 (顺便说一下,我给两个答案都点了赞) - Marc
1
我不确定JavaScript是否真的区分“同一函数的新闭包”和“新函数”。据我所知,它们都只是Function的不同实例。 - Samuel Edwin Ward
2
如果你真的想用闭包的方式来完成第二个例子,你只需要在函数表达式内部使用eval()调用即可。而且如果我们要讨论这两种方法的局限性,使用Function构造函数的方式完全无法访问从中构造new Function的函数的局部变量,这使得这种方法比闭包方法弱很多,并且无法实现许多有用的功能。 - Mark Amery
显示剩余5条评论

10

以下是一个在 JavaScript 中运行时创建函数的示例:

function makeIncrementer(value) {
    return function(x) {
        return x+value;
    }
}

它接受一个值,并返回一个将该值加到其输入的函数。

以下是一些调用它的示例:

var f = makeIncrementer(5);
f(2); // 7
f.call(null, 3); // 8
f.apply(null, [4]); /// 9
var object = {};
object.increment = f;
object.increment(5); // 10

@SamuelEdwinWard,我想要公开表扬你的回答是第一个也是最符合问题的答案。说实话,在你和其他人之间做出选择是随意的。感谢你花费时间回答问题。 - Thomas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接