我正在尝试编写一个JavaScript函数,该函数将返回其第一个参数(函数),其所有其余参数作为该函数的预设参数。
所以:
function out(a, b) { document.write(a + " " + b); } function setter(...) {...} setter(out, "hello")("world"); setter(out, "hello", "world")();
两次输出“hello world”。对于setter的一些实现
我遇到了第一次尝试操作arguments数组的问题,但似乎有更好的方法来做到这一点。
答案 0 :(得分:96)
首先,你需要一个部分 - there is a difference between a partial and a curry - 这就是你所需要的,没有框架:
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。以下是a blog post on the difference的引用:
当部分应用程序接受一个函数并从中构建一个函数,该函数接受较少的参数,currying构建函数,这些函数通过函数组合获取多个参数,每个参数都采用一个参数。
希望有所帮助。
答案 1 :(得分:3)
curried javascript您要找的是什么?
答案 2 :(得分:2)
如果你使用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")();
dojox.lang.functional.curry模块中提供了另一个常规工具(在Functional fun in JavaScript with Dojo中有记录 - 只需在此页面上查看“咖喱”)。具体来说,您可能需要查看curry()和partial()。
curry()累积参数(如在你的例子中),但有一点不同:只要arity满足,它就会调用返回值的函数。实现你的例子:
df.curry(out)("hello")("world");
df.curry(out)("hello", "world");
请注意,最后一行最后没有“()” - 它会自动调用。
partial()允许随机替换参数:
df.partial(out, df.arg, "world")("hello");
答案 3 :(得分:2)
使用Javascript' apply()
,您可以修改function prototype
Function.prototype.pass = function() {
var args = arguments,
func = this;
return function() {
func.apply(this, args);
}
};
然后,您可以将其称为out.pass('hello','world')
apply
获取第二个参数/参数的数组。
arguments
是函数内部可用的属性,它包含数组中的所有参数,如结构。
另一种常用方法是使用bind
loadedFunc = func.bind(this, v1, v2, v3);
然后
loadedFunc() === this.func(v1,v2,v3);
答案 4 :(得分:1)
您可以使用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")();
我的setter
功能实际上非常简单。最长的部分是获取参数列表。我会像这样分解代码:
func.bind.apply(func, [window].concat([].slice.call(arguments).slice(1)))
func.bind.apply( ) // need to use apply to pass multiple arguments as an array to bind()
func, // apply needs a context to be run in
[window].concat( ) // pass an array of arguments to bind(), starting with window, to be the global context
[].slice.call(arguments).slice(1) // convert the arguments list to an array, and chop off the initial value
these browsers支持:Chrome 7 +,Firefox 4 +,IE9 +。 MDN(在开头链接)有一个polyfill。
答案 5 :(得分:0)
** 编辑:请参阅Jason Bunting的回复。这个答案实际上显示了链接众多调用的一种低级别的方式,而不是针对某些参数的预设的单个调用。如果这个答案实际上有助于解决类似的问题,你应该确保使用jason推荐的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函数本身,但是因为我使用'eval'而稍微安全一些。
答案 6 :(得分:0)
在不立即调用函数的情况下(例如,在等待用户确认时)实现参数预设的简便方法是将函数“修饰”在另一个匿名函数中。
代替:exportFile(docType)
执行:function(){ return exportFile(docType) }
答案 7 :(得分:0)
使用闭包是另一种选择。使用返回其他函数的函数!