如何在JavaScript函数调用中预先设置参数? (部分function应用)

我正在尝试编写一个JavaScript函数,将其第一个参数(函数)与其余所有参数作为预设参数返回给该函数。

所以:

  function out(a,b){
     document.write(a +“”+ b);
 }

函数setter(...){...}

 setter(out,“hello”)(“world”);
 setter(out,“hello”,“world”)();

会输出两次“hello world”。 对于setter的一些实现

我在第一次尝试操作参数数组时遇到了一个问题,但似乎有更好的方法来做到这一点。

首先,你需要一个部分 – 部分和咖喱之间的区别 – 这是你所需要的, 没有一个框架

 function partial(func /*, 0..n args */) { var args = Array.prototype.slice.call(arguments, 1); return function() { var allArguments = args.concat(Array.prototype.slice.call(arguments)); return func.apply(this, allArguments); }; } 

现在,用你的例子,你可以做到你正在做什么:

 partial(out, "hello")("world"); partial(out, "hello", "world")(); // and here is my own extended example var sayHelloTo = partial(out, "Hello"); sayHelloTo("World"); sayHelloTo("Alex"); 

partial()函数可以用来实现,但不是 currying。 下面是一篇关于差异的博客文章引用:

如果部分应用程序接受一个函数,并且从中构build一个函数,而这个函数只需要较less的参数,那么currying函数就可以通过函数的组合构build函数,每个函数只有一个参数。

希望有所帮助。

curried javascript你在找什么?

如果您使用Dojo,则只需调用dojo.hitch()即可完成您想要的操作。 几乎 – 因为它也可以用来包装上下文。 但是你的榜样是第一个:

 dojo.hitch(out, "hello")("world"); dojo.hitch(out, "hello", "world")(); 

以及:

 var A = { sep: ", ", out: function(a, b){ console.log(a + this.sep + b); } }; // using functions in context dojo.hitch(A, A.out, "hello")("world"); dojo.hitch(A, A.out, "hello", "world")(); // using names in context dojo.hitch(A, "out", "hello")("world"); dojo.hitch(A, "out", "hello", "world")(); 

dojo.hitch()是Dojo Base的一部分,所以只要你包含了dojo.js,它就在你的面前。

另一个通用的工具是在dojox.lang.functional.curry模块中提供的(在Dojo中用JavaScript实现的函数中有说明 – 只需要在这个页面上查看“curry”)。 具体来说,你可能想看看咖喱()和部分()。

curry()会累积参数(就像你的例子),但有一点不同:一旦arity被满足,它就调用返回值的函数。 实施你的例子:

 df.curry(out)("hello")("world"); df.curry(out)("hello", "world"); 

请注意,最后一行最后没有“()” – 它会自动调用。

partial()允许随机replace参数:

 df.partial(out, df.arg, "world")("hello"); 

**编辑:见杰森·邦廷的回应。 这个答案实际上表明了一种连接多次打出电话的次要方式,而不是一个带有预设的单个电话。 如果这个答案实际上有助于解决类似的问题,那么你应该确保按照Jason的build议来使用apply和call,而不是使用我想象中的eval。 **

那么…你的出门实际上会在这里写下“未定义”的东西……但是这应该接近你想要的:

 function out(a, b) { document.write(a + " " + b); } function getArgString( args, start ) { var argStr = ""; for( var i = start; i < args.length; i++ ) { if( argStr != "" ) { argStr = argStr + ", "; } argStr = argStr + "arguments[" + i + "]" } return argStr; } function setter(func) { var argStr = getArgString( arguments, 1 ); eval( "func( " + argStr + ");" ); var newSettter = function() { var argStr = getArgString( arguments, 0 ); if( argStr == "" ) { argStr = "func"; } else { argStr = "func, " + argStr; } return eval( "setter( " + argStr + ");" ); } return newSettter; } setter(out, "hello")("world"); setter(out, "hello", "world")(); 

我可能会将getArgString中的代码移入setter函数本身,尽pipe…因为使用了“eval”,所以更安全一些。

你可以使用Function.prototype.bind() 。 这是一个ES5添加。

除了设置函数的上下文( this值)的通用用法之外,它还可以设置部分参数。

 function out(a, b) { document.write(a + " " + b); } function setter(func) { return func.bind.apply(func, [window].concat([].slice.call(arguments).slice(1))); } setter(out, "hello")("world"); setter(out, "hello", "world")(); 
 function myLog(arg1,arg2,arg3){ return function(){ //you can use the arguments from the parent scope console.log(arg1+" "+arg2+" "+arg3); }; } var passMeAnywhere = myLog(1,2,3); //execute the function, args will be in the immediate lexical scope. passMeAnywhere(); //One of the previous posts showed a way for context binding //Context binding allows any context //New is not required with binding