多个箭头函数在 JavaScript 中是什么意思?
我一直在阅读一堆 React 代码,我看到这样我不明白的东西:
handleChange = field => e => {
e.preventDefault();
/// Do something here
}
我一直在阅读一堆 React 代码,我看到这样我不明白的东西:
handleChange = field => e => {
e.preventDefault();
/// Do something here
}
这是一个咖喱功能
首先,使用两个参数检查此函数...
const add = (x, y) => x + y
add(2, 3) //=> 5
在这里,它再次以咖喱形式...
const add = x => y => x + y
这是相同的1代码,没有箭头函数...
const add = function (x) {
return function (y) {
return x + y
}
}
关注回报
从另一个角度来可视化它可能会有所帮助。我们知道箭头函数的工作方式是这样的 - 让我们特别注意返回值。
const f = someParam => returnValue
所以我们的函数返回一个函数 - 我们可以使用括号来增加清晰度。粗体文本是我们函数的返回值add
add
const add = x => (y => x + y)
换句话说,某个数字返回一个函数add
add(2) // returns (y => 2 + y)
调用已启动的函数
因此,为了使用我们的curried函数,我们必须以不同的方式调用它......
add(2)(3) // returns 5
这是因为第一个(外部)函数调用返回第二个(内部)函数。只有在调用第二个函数之后,我们才能真正得到结果。如果我们将呼叫分开两条线,这一点就更明显了......
const add2 = add(2) // returns function(y) { return 2 + y }
add2(3) // returns 5
将我们的新理解应用于您的代码
好了,现在我们了解了它是如何工作的,让我们来看看你的代码。
handleChange = field => e => {
e.preventDefault()
/// Do something here
}
我们将从不使用箭头函数来表示它开始...
handleChange = function(field) {
return function(e) {
e.preventDefault()
// Do something here
// return ...
};
};
但是,由于箭头功能在词法上绑定,它实际上看起来更像这样......this
handleChange = function(field) {
return function(e) {
e.preventDefault()
// Do something here
// return ...
}.bind(this)
}.bind(this)
也许现在我们可以更清楚地看到这在做什么。该函数正在为指定的 创建函数。这是一种方便的 React 技术,因为您需要在每个输入上设置自己的侦听器,以便更新应用程序状态。通过使用该函数,我们可以消除所有重复的代码,这些代码会导致为每个字段设置侦听器。凉!handleChange
field
handleChange
change
1 在这里,我不必在词法上绑定,因为原始函数不使用任何上下文,因此在这种情况下保留它并不重要。this
add
更多箭头
如有必要,可以对两个以上的箭头函数进行排序 -
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函数,但在调用站点,似乎我们可以提供任意数量的参数。咖喱是阿瑞提的抽象$
-
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
部分申请
部分应用是一个相关的概念。它允许我们部分应用函数,类似于咖喱,除了函数不必以咖喱形式定义 -
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
这是一个工作演示,您可以在自己的浏览器中玩 -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">
简要
它是一个返回以简短方式编写的另一个函数的函数。
const handleChange = field => e => {
e.preventDefault()
// Do something here
}
// is equal to
function handleChange(field) {
return function(e) {
e.preventDefault()
// Do something here
}
}
为什么?
您是否曾经遇到过需要创建可自定义功能的情况?或者,也许您有一个具有固定参数的回调函数,但是您需要在避免全局变量的同时发送额外的变量?如果你的回答是肯定的,那么这就是如何做到这一点的方法。
例如,我们有一个带有回调的按钮。我们想要传递给函数,但是,只接受一个参数,所以我们不能这样做:onClick
id
onClick
event
const handleClick = (event, id) {
event.preventDefault()
// Dispatch some delete action by passing record id
}
这是行不通的!
在这里,作为解决方案,我们编写一个函数,该函数在其变量范围内返回另一个函数,而不使用任何全局变量:id
const handleClick = id => event {
event.preventDefault()
// Dispatch some delete action by passing record id
}
const Confirm = props => (
<div>
<h1>Are you sure to delete?</h1>
<button onClick={handleClick(props.id)}>
Delete
</button>
</div
)
功能组成
多个箭头函数也称为“咖喱函数”,它们用于函数组合。
// It is just an example, unfortunately, redux does not export dispatch function
import {dispatch, compose} from 'redux'
const pickSelectedUser = props => {
const {selectedName, users} = props
const foundUser = users.find(user => user.name === selectedName)
return foundUser.id
}
const deleteUser = userId => event => {
event.preventDefault()
dispatch({
type: `DELETE_USER`,
userId,
})
}
// The compose function creates a new function that accepts a parameter.
// The parameter will be passed throw the functions from down to top.
// Each function will change the value and pass it to the next function
// By changing value it was not meant a mutation
const handleClick = compose(
deleteUser,
pickSelectedUser,
)
const Confirm = props => (
<div>
<h1>Are you sure to delete?</h1>
<button onClick={handleClick(props)}>
Delete
</button>
</div
)