Javascript 为什么在curry函数的这个实现中需要使用bind
有一个来自的咖喱功能 为什么在(*)行中需要使用绑定?它可以被替换为Javascript 为什么在curry函数的这个实现中需要使用bind,javascript,currying,Javascript,Currying,有一个来自的咖喱功能 为什么在(*)行中需要使用绑定?它可以被替换为 return curry(fn, arity, ...args) // line(**) ?使用函数#bind只有两个原因: 当您想要将函数绑定到特定的上下文对象时。实际上,当您希望提前确保函数中的this关键字将引用特定的已知对象时 当您想要预先定义一些参数时,a.k.a.“部分函数应用程序” 第二种情况很好地说明了函数currying的意义——使N元函数可以灵活调用,如: fn(arg1,arg2,…,argN),或
return curry(fn, arity, ...args) // line(**)
?使用
函数#bind
只有两个原因:
this
关键字将引用特定的已知对象时
,或fn(arg1,arg2,…,argN)
,或fn(arg1,arg2,…)(argN)
,或fn(arg1,arg2)(…,argN)
fn(arg1)(arg2)(…)(argN)
curry()
使用这3个参数调用worker函数并返回结果。这使得
fn(arg1、arg2、arg3)
成为可能curry()
不调用辅助函数,但必须返回一个新函数,该函数接受剩余数量的参数。这使得所有
fn(arg1)(arg2,arg3)
和fn(arg1,arg2)(arg3)
和fn(arg1)(arg2)(arg3)
成为可能Function#bind
介绍了第二种情况:它为辅助函数创建一个新的包装函数,并用给定的值预先填充辅助函数的一些参数槽。上下文对象与该意图无关,因此在这里使用null
就可以了
const curry = (fn, arity = fn.length, ...args) =>
// enough arguments ? call : remember arguments so far & defer
args.length >= arity ? fn(...args) : curry.bind(null, fn, arity, ...args);
所以要回答这个问题:不,您不能使用返回curry(fn,arity,…args)
,因为这不做最重要的事情,也就是创建一个新函数
示例:假设我们有一个worker函数,它搜索字符串并返回命中数
const search = (str, substr) => {
var hits = 0, pos = 0;
while (true) {
pos = str.indexOf(substr, pos) + 1;
if (pos) hits++; else return hits;
}
}
现在,我们可以创建一个可以记住目标字符串的咖喱版本,只需切换最后一个参数:
const flexibleSearch = curry(search);
const reusableSearch = flexibleSearch("... a ... b ... c ... a ... b ... a");
reusableSearch("a") // -> 3
reusableSearch("b") // -> 2
reusableSearch("c") // -> 1
reusableSearch("d") // -> 0
@托马拉克是对的
假设您有一个函数,它接受100个参数fn(1,2,3,…100){}
fn.bind(null,99100)
使用预设前导参数创建一个新函数。在我们的示例中,将使用参数1,2,…97,98的默认值,并期望有两个参数作为新函数的输入,该函数将用作参数99和100
在本例中,我们使用函数来接受部分参数
你可以通过这些来获得更深入的理解
和
fn.bind()
始终返回新函数。而fn()
将调用该函数。“它可以替换为返回咖喱(fn,arity,…args)
”您可以替换为返回(…args2)=>咖喱(fn,arity,…args,…args2)
您的答案非常详细和彻底。我对你的答案投了赞成票,因为它非常详细和准确。我仍然在添加一个答案来简化事情。
const flexibleSearch = curry(search);
const reusableSearch = flexibleSearch("... a ... b ... c ... a ... b ... a");
reusableSearch("a") // -> 3
reusableSearch("b") // -> 2
reusableSearch("c") // -> 1
reusableSearch("d") // -> 0