That is a curried function
(那是一个咖喱函数)
First, examine this function with two parameters …
(首先,使用两个参数检查此功能……)
const add = (x, y) => x + y
add(2, 3) //=> 5
Here it is again in curried form …
(这里又是咖喱形式的……)
const add = x => y => x + y
Here is the same 1 code without arrow functions …
(这是没有箭头功能的相同1个代码……)
const add = function (x) {
return function (y) {
return x + y
}
}
Focus on return
(专注于return
)
It might help to visualize it another way.
(用另一种方式可视化可能会有所帮助。)
We know that arrow functions work like this – let's pay particular attention to the return value .(我们知道箭头函数是这样工作的-让我们特别注意返回值 。)
const f = someParam => (returnValue)
So our add
function returns a function – we can use parentheses for added clarity.
(因此,我们的add
函数返回一个函数 –我们可以使用括号来增加清晰度。)
The bolded text is the return value of our function add
(粗体字是我们函数add
的返回值)
const add = x => ((y => x + y))
In other words add
of some number returns a function
(换句话说,一些数字的add
返回一个函数)
add(2) // returns (y => 2 + y)
Calling curried functions
(调用咖喱函数)
So in order to use our curried function, we have to call it a bit differently …
(因此,为了使用我们的curried函数,我们必须对其进行一些不同的调用……)
add(2)(3) // returns 5
This is because the first (outer) function call returns a second (inner) function.
(这是因为第一个(外部)函数调用返回了第二个(内部)函数。)
Only after we call the second function do we actually get the result.(只有在调用第二个函数之后,我们才真正得到结果。)
This is more evident if we separate the calls on two lines …(如果我们将呼叫分隔在两行上,则更明显……)
const add2 = add(2) // returns function(y) { return 2 + y }
add2(3) // returns 5
Applying our new understanding to your code
(将我们的新知识应用于您的代码)
related: ”What's the difference between binding, partial application, and currying?”
(相关: “绑定,部分应用和柯林有什么区别?”)
OK, now that we understand how that works, let's look at your code
(好,现在我们了解了它的工作原理,让我们看一下您的代码)
handleChange = field => e => {
e.preventDefault()
/// Do something here
}
We'll start by representing it without using arrow functions …
(我们将从不使用箭头功能来表示它开始……)
handleChange = function(field) {
return function(e) {
e.preventDefault()
// Do something here
// return ...
};
};
However, because arrow functions lexically bind this
, it would actually look more like this …
(但是,由于arrow函数用词法绑定了this
,因此实际上看起来更像这样……)
handleChange = function(field) {
return function(e) {
e.preventDefault()
// Do something here
// return ...
}.bind(this)
}.bind(this)
Maybe now we can see what this is doing more clearly.
(也许现在我们可以更清楚地看到它在做什么。)
The handleChange
function is creating a function for a specified field
.(handleChange
函数正在为指定field
创建一个函数。)
This is a handy React technique because you're required to setup your own listeners on each input in order to update your applications state.(这是一种方便的React技术,因为您需要在每个输入上设置自己的侦听器以更新您的应用程序状态。)
By using the handleChange
function, we can eliminate all the duplicated code that would result in setting up change
listeners for each field.(通过使用handleChange
函数,我们可以消除所有重复的代码,这些代码将导致为每个字段设置change
侦听器。)
Cool!(凉!)
1 Here I did not have to lexically bind this
because the original add
function does not use any context, so it is not important to preserve it in this case.
(1在这里,我不必用词法绑定this
因为原始的add
函数不使用任何上下文,因此在这种情况下保留它并不重要。)
Even more arrows
(甚至更多的箭)
More than two arrow functions can be sequenced, if necessary -
(如有必要,可以排序两个以上的箭头功能-)
const three = a => b => c =>
a + b + c
const four = a => b => c => d =>
a + b + c + d
three (1) (2) (3) // 6
four (1) (2) (3) (4) // 10
Curried functions are capable of surprising things.
(咖喱函数能够使人惊讶。)
Below we see $
defined as a curried function with two parameters, yet at the call site, it appears as though we can supply any number of arguments.(在下面,我们看到$
被定义为具有两个参数的咖喱函数,但是在调用站点,似乎我们可以提供任意数量的参数。)
Currying is the abstraction of arity -(柯里是抽象元数 -)
const $ = x => k => $ (k (x)) const add = x => y => x + y const mult = x => y => x * y $ (1) // 1 (add (2)) // + 2 = 3 (mult (6)) // * 6 = 18 (console.log) // 18 $ (7) // 7 (add (1)) // + 1 = 8 (mult (8)) // * 8 = 64 (mult (2)) // * 2 = 128 (mult (2)) // * 2 = 256 (console.log) // 256
Partial application
(部分申请)
Partial application is a related concept.
(部分应用是一个相关的概念。)
It allows us to partially apply functions, similar to currying, except the function does not have to be defined in curried form -(它允许我们部分地应用函数,类似于currying,除了不必以咖喱形式定义函数-)
const partial = (f, ...a) => (...b) =>
f (...a, ...b)
const add3 = (x, y, z) =>
x + y + z
partial (add3) (1, 2, 3) // 6
partial (add3, 1) (2, 3) // 6
partial (add3, 1, 2) (3) // 6
partial (add3, 1, 2, 3) () // 6
partial (add3, 1, 1, 1, 1) (1, 1, 1, 1, 1) // 3
Here's a working demo of partial
you can play with in your own browser -
(这是您可以在自己的浏览器中播放的partial
工作演示-)
const partial = (f, ...a) => (...b) => f (...a, ...b) const preventDefault = (f, event) => ( event .preventDefault () , f (event) ) const logKeypress = event => console .log (event.which) document .querySelector ('input[name=foo]') .addEventListener ('keydown', partial (preventDefault, logKeypress))
<input name="foo" placeholder="type here to see ascii codes" size="50">