我读了一堆React代码,我看到了这样的东西,我不理解:
handleChange = field => e => {
e.preventDefault();
/// Do something here
}
我读了一堆React代码,我看到了这样的东西,我不理解:
handleChange = field => e => {
e.preventDefault();
/// Do something here
}
当前回答
理解箭头函数的可用语法将使你理解它们在“链接”时引入的行为,就像你提供的例子一样。
当一个箭头函数不带大括号(带或不带多个形参)时,将隐式返回构成函数体的表达式。在您的示例中,该表达式是另一个箭头函数。
No arrow funcs Implicitly return `e=>{…}` Explicitly return `e=>{…}`
---------------------------------------------------------------------------------
function (field) { | field => e => { | field => {
return function (e) { | | return e => {
e.preventDefault() | e.preventDefault() | e.preventDefault()
} | | }
} | } | }
使用箭头语法编写匿名函数的另一个优点是,它们在词法上绑定到定义它们的作用域。来自MDN上的“箭头函数”:
与函数表达式相比,箭头函数表达式具有更短的语法,并且在词法上绑定this值。箭头函数总是匿名的。
考虑到它来自一个reactjs应用程序,这在您的示例中尤其相关。正如@naomik所指出的,在React中,你经常使用这个来访问组件的成员函数。例如:
Unbound Explicitly bound Implicitly bound
------------------------------------------------------------------------------
function (field) { | function (field) { | field => e => {
return function (e) { | return function (e) { |
this.setState(...) | this.setState(...) | this.setState(...)
} | }.bind(this) |
} | }.bind(this) | }
其他回答
这可能不是完全相关的,但由于提到的react用例的问题(我一直碰到这个SO线程):这里没有明确提到双箭头函数的一个重要方面。 只有“第一个”箭头(函数)被命名(因此可以被运行时“区分”),任何后面的箭头都是匿名的,从React的角度来看,在每次渲染时都算作一个“新”对象。
因此,双箭头函数将导致任何PureComponent一直重新渲染。
例子
你有一个带有更改处理程序的父组件:
handleChange = task => event => { ... operations which uses both task and event... };
并且像这样渲染:
{ tasks.map(task => <MyTask handleChange={this.handleChange(task)}/> }
然后在输入或单击时使用handleChange。这些都很好用,看起来很不错。但是这意味着任何会导致父对象重新渲染的变化(比如一个完全不相关的状态变化)也会重新渲染你的所有MyTask,即使它们是PureComponents。
这可以通过多种方式缓解,例如传递'outmost'箭头和你将提供给它的对象,或者编写一个自定义shouldUpdate函数,或者回到基础,例如编写命名函数(并手动绑定This…)
短暂的
它是一个返回另一个简单函数的函数。
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,这使得id和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
)
函数组合
多箭头函数也被称为“咖喱函数”,用于函数组合。
import {compose} from 'redux'
import {store} from './store.js'
const pickSelectedUser = props => {
const {selectedName, users} = props
const foundUser = users.find(user => user.name === selectedName)
return foundUser.id
}
const deleteUser = userId => event => {
event.preventDefault()
store.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
)
可以这样想,每次你看到一个箭头,你就用函数替换它。函数参数在箭头之前定义。 在你的例子中:
field => // function(field){}
e => { e.preventDefault(); } // function(e){e.preventDefault();}
然后一起:
function (field) {
return function (e) {
e.preventDefault();
};
}
从文档中可以看出:
// Basic syntax:
(param1, param2, paramN) => { statements }
(param1, param2, paramN) => expression
// equivalent to: => { return expression; }
// Parentheses are optional when there's only one argument:
singleParam => { statements }
singleParam => expression
一般提示:如果你对任何新的JavaScript语法以及它的编译方式感到困惑,你可以查看Babel。例如,在Babel中复制您的代码并选择ES 2015预设将会给出如下输出
handleChange = function handleChange(field) {
return function (e) {
e.preventDefault();
// Do something here
};
};
理解箭头函数的可用语法将使你理解它们在“链接”时引入的行为,就像你提供的例子一样。
当一个箭头函数不带大括号(带或不带多个形参)时,将隐式返回构成函数体的表达式。在您的示例中,该表达式是另一个箭头函数。
No arrow funcs Implicitly return `e=>{…}` Explicitly return `e=>{…}`
---------------------------------------------------------------------------------
function (field) { | field => e => { | field => {
return function (e) { | | return e => {
e.preventDefault() | e.preventDefault() | e.preventDefault()
} | | }
} | } | }
使用箭头语法编写匿名函数的另一个优点是,它们在词法上绑定到定义它们的作用域。来自MDN上的“箭头函数”:
与函数表达式相比,箭头函数表达式具有更短的语法,并且在词法上绑定this值。箭头函数总是匿名的。
考虑到它来自一个reactjs应用程序,这在您的示例中尤其相关。正如@naomik所指出的,在React中,你经常使用这个来访问组件的成员函数。例如:
Unbound Explicitly bound Implicitly bound
------------------------------------------------------------------------------
function (field) { | function (field) { | field => e => {
return function (e) { | return function (e) { |
this.setState(...) | this.setState(...) | this.setState(...)
} | }.bind(this) |
} | }.bind(this) | }