Javascript 如何捕获函数中所需的参数数(curry函数部分应用程序)
我正在处理curring函数和部分应用程序, 我正在尝试改进Schonfilize的功能:Javascript 如何捕获函数中所需的参数数(curry函数部分应用程序),javascript,design-patterns,Javascript,Design Patterns,我正在处理curring函数和部分应用程序, 我正在尝试改进Schonfilize的功能: function schonfinkelize(fn){ var slice = Array.prototype.slice, stored_args = slice.call(arguments, 1); return function(){
function schonfinkelize(fn){
var
slice = Array.prototype.slice,
stored_args = slice.call(arguments, 1);
return function(){
var
new_args = slice.call(arguments),
args = stored_args.concat(new_args);
return fn.apply(null, args);
}
}
此函数允许作为参数传递函数和作为参数传递的函数的一部分(部分应用),因此第一次返回函数时,以及再次启动函数时,都会返回结果
function add(x, y, z){
return x + y + z;
}
var val = schonfinkelize(add, 1, 2);
console.log( val(3) ) // console output--> 6
我想检查schonfilize函数“add”所需的参数数量(但它应该适用于每个函数),这样我就可以选择何时返回另一个函数或直接返回函数“add”的结果
因为如果我以这种方式使用Schonflize:
var val2 = schonfinkelize(add, 1, 2, 3);
console.log( val2 ) // --> function
console.log( val2() ) // --> 6
我必须启动函数两次,如果参数足够,我希望避免这种行为并直接定义值
一个可能的解决办法是:
function schonfinkelize(fn){
var
slice = Array.prototype.slice,
stored_args = slice.call(arguments, 1);
//* I have added this ********
if(fn.apply(null, stored_args))
return fn.apply(null, stored_args);
//****************************
return function(){
var
new_args = slice.call(arguments),
args = stored_args.concat(new_args);
return fn.apply(null, args);
}
}
可能是因为如果fn.apply(null,stored_args)返回的内容不是“null”或“NaN”,但我认为不是真正执行的,然后我希望使用参数。我认为没有正确的方法来确定任意函数的参数数。如果有必要,我更喜欢将
len
存储在函数中,并检查它是否已定义,如果已定义,并且如果fn.len==stored_args.length
则返回只返回值的函数
function schonfinkelize(fn){
var
slice = Array.prototype.slice,
stored_args = slice.call(arguments, 1);
if (fn.len != undefined && fn.len == stored_args.length) {
var val = fn.apply(null, stored_args);
return function () {
return val;
};
}
return function () {
var
new_args = slice.call(arguments),
args = stored_args.concat(new_args);
return fn.apply(null, args);
};
}
var f = function (a, b, c) {
return a + b + c;
};
f.len = 3;
var g = schonfinkelize(f, 1, 2);
alert(g); // function () { var new_args = slice.call(arguments), args = stored_args.concat(new_args); return fn.apply(null, args); };
alert(g(3)); // 6
var g = schonfinkelize(f, 1, 2, 3);
alert(g); // function () { return val; };
alert(g()); // 6
function schonfinkelize(fn) {
if (fn.length === arguments.length - 1)
return fn.apply(this, [].slice.call(arguments, 1));
var
slice = Array.prototype.slice,
stored_args = slice.call(arguments, 1);
return function(){
var
new_args = slice.call(arguments),
args = stored_args.concat(new_args);
return fn.apply(null, args);
}
}
只要您要求为传递的函数定义的参数反映最终接收的实际参数数量,就可以使用函数的
.length
属性将传递的参数与预期参数进行比较
function schonfinkelize(fn) {
if (fn.length === arguments.length - 1)
return fn.apply(this, [].slice.call(arguments, 1));
var
slice = Array.prototype.slice,
stored_args = slice.call(arguments, 1);
return function(){
var
new_args = slice.call(arguments),
args = stored_args.concat(new_args);
return fn.apply(null, args);
}
}
旁注。。。如果将
fn
缓存在新变量中,并使用此值覆盖第一个参数,然后使用.call.apply()
,则可以避免使用.slice()
if (fn.length === arguments.length - 1) {
var func = fn;
arguments[0] = this;
return func.call.apply(func, arguments);
}
在严格模式浏览器中,您甚至可以避免使用make这个新变量,因为参数不再映射到参数中的更改。但是,这在不支持严格模式的浏览器中不起作用。我还想建议对代码进行个人改进,但我不得不说,由于斜视解决了问题,只需建议我使用属性.length。
在我看来,下一个级别是允许创建一个分部函数,可以在每次需要时调用,直到完成填充所有参数为止,我还简化了代码:
function schonfinkelize(fn, stored_args){
if(fn.length == stored_args.length)
return fn.apply(null, stored_args);
return function(){
var
new_args = arguments[0],
args = stored_args.concat(new_args);
if(fn.length == args.length)
return fn.apply(null, args);
return schonfinkelize(fn, args);
}
}
function add(x, y, w, z){
return x + y + w + z;
}
var
val = schonfinkelize(add, [1, 2, 3, 4]),
val2 = schonfinkelize(add, [1, 2]),
val3 = schonfinkelize(add, [1]);
// checking
console.log(val); // output --> 10 // called only 1 time
console.log(val2([3, 4])); // output --> 10 // called in 2 times
val3 = val3([2]);
val3 = val3([3]);
console.log(val3([4])); // output --> 10 // called 4 times!
如果您可以假设传递的函数只需要定义为参数的参数,那么您可以使用函数的.length
属性来确定有多少参数。因此,您的add
函数将具有add.length;//3
。因此,您可以将该数字与传递给返回函数的参数数量进行比较。我试图避免使用属性。length,因为它取所有传递参数的数量,所以可以是每个数量的数字,但如果我遵循您的推理,您是对的。我也曾想过使用适当的属性来附加到作用域,如v.len=3(如Speransky Danil的响应),但我希望找到函数的固有适当性,但在这一点上,我认为它不存在……函数的固有属性就是我在上面的评论中描述的。函数具有.length
属性,该属性描述为该函数定义的参数数量。是的,一个人可以添加一个.len
,但是为什么同一个人不简单地定义适当数量的参数呢?…在schonlinkize()函数的顶部是这样的<代码>如果(fn.length-1==arguments.length)返回fn.apply(这是slice.call(arguments,1))对不起,我没听懂,你说得对!我也有同样的想法,但我希望有一个天生的习惯来发现这个数字,但似乎它并不存在。