當(dāng)我們想起箭頭函數(shù)時(shí),腦海里可能會(huì)浮現(xiàn)
棒
,酷
,簡(jiǎn)潔
,有趣
等形容詞,其實(shí),我們存在一些更充分的理由
使我們?cè)诼?lián)想起箭頭函數(shù)時(shí)不得不想到的
解決 this
引起的問(wèn)題
箭頭函數(shù)不會(huì)在函數(shù)體內(nèi)重新定義 this
的值,這使得在回調(diào)中的行為更容易預(yù)測(cè),并且避免了 this
在回調(diào)中潛存的 bug
下面我們來(lái)看一個(gè) example
我們期望點(diǎn)擊按鈕,改變按鈕顏色,代碼如下
class BrokenButton extends React.Component {
render() {
return (
<button onClick={this.handleClick} style={this.state}>
Set background to red
</button>
);
}
handleClick() {
this.setState({ backgroundColor: "red" });
}
}
render(<BrokenButton />, document.getElementById("root"));
然而,當(dāng)我們點(diǎn)擊按鈕時(shí),什么效果都沒(méi)有,為什么會(huì)這樣呢
其實(shí),不是 handleClick
方法沒(méi)有起作用,因?yàn)?JavaScript
中壓根沒(méi)有方法, JavaScript
中只有函數(shù),而函數(shù)中的 this
存在一些規(guī)則,正是這些規(guī)則,讓上面的 handleClick
中的 this
值變成了 null
你需要清楚明白的是: 你無(wú)法確定一個(gè)方法函數(shù)中 this 的指向,因?yàn)樗闹蹈瘮?shù)的調(diào)用方式有關(guān)
除非,你使用 箭頭函數(shù)
,因?yàn)榧^函數(shù)中 this
的值是繼承自 外圍作用域
class Button extends React.Component {
render() {
return (
<button
onClick={() => this.setState({ backgroundColor: "red" })}
style={this.state}
>
Set background to red
</button>
);
}
}
render(<Button />, document.getElementById("root"));
現(xiàn)在就對(duì)了,接下來(lái),我們繼續(xù)
瀏覽器支持
瀏覽器對(duì) 箭頭函數(shù)
的支持大概是 73%
,因?yàn)槟壳埃?code>IE 并不支持。但如果你已經(jīng)意識(shí)到這一點(diǎn),并且你還會(huì)代碼轉(zhuǎn)譯
,這對(duì)你來(lái)說(shuō)就不算什么問(wèn)題
性能問(wèn)題
大家都發(fā)現(xiàn)了,箭頭函數(shù)
書(shū)寫(xiě)起來(lái)是非常容易的,但書(shū)寫(xiě)忒多的函數(shù),也會(huì)造成一些問(wèn)題
定義函數(shù)是昂貴的
瀏覽器每執(zhí)行一次 =>
,就需要?jiǎng)?chuàng)建一個(gè) 新的函數(shù)對(duì)象
,這其實(shí)是一個(gè)比較 昂貴
的操作
當(dāng)然,如果你不是想構(gòu)建一個(gè) 性能超級(jí)無(wú)敵宇宙螺旋棒
的組件,渲染一個(gè) 非常長(zhǎng)
的列表或 非常大
的表格,你也不會(huì)發(fā)現(xiàn)這是一個(gè) 問(wèn)題
所以,如果你的組件只是在頁(yè)面中渲染個(gè)幾次,你也 沒(méi)必要忒擔(dān)心
性能這方面的問(wèn)題
兩個(gè)相同的箭頭函數(shù)并不相等
為了讓大家意識(shí)到這個(gè)問(wèn)題,接下來(lái),我們用 ==
比較一下兩個(gè)相同的箭頭函數(shù)相不相等
const a = x => x,
b = x => x;
render(
<div>
<h3>
Are <code>a</code> and <code>b</code> equal by <code>==</code>?
</h3>
<p>
{a == b ? "Yes!" : "No :("}
</p>
</div>,
document.getElementById("root")
);
如果你在 render
中使用箭頭函數(shù),那么你在每次調(diào)用 render
時(shí)都會(huì)去創(chuàng)建一個(gè)新的函數(shù)對(duì)象,此時(shí),即使使用 PureComponent
和 shouldComponentUpdate
也起不到優(yōu)化作用
你可以在下面實(shí)例中看清這一點(diǎn),其中,<PropChangeCounter />
組件用于打印 props
改變的次數(shù)
import PropChangeCounter from "react-armory-prop-change-counter";
class App extends React.Component {
constructor(props) {
super(props);
this.state = { email: "" };
}
render() {
return (
<div>
<input
placeholder="Email"
value={this.state.email}
onChange={e => this.setState({ email: e.target.value })}
/>
<PropChangeCounter
constant={"this doesn't change"}
value={this.state.email}
onChange={e => this.setState({ email: e.target.value })}
/>
</div>
);
}
}
render(<App />, document.getElementById("root"));
只定義一次
如果你覺(jué)得 性能
對(duì)你的組件很重要,那么你肯定會(huì)想如果在組件中只定義箭頭函數(shù) 一次
該有多好
其中一種實(shí)現(xiàn)方式是在 constructor
中使用箭頭函數(shù),當(dāng)然,對(duì)于復(fù)雜些的組價(jià)來(lái)說(shuō),這也可能會(huì)變的笨拙
如果你使用了 Babel
或 create-react-app
構(gòu)建你的應(yīng)用,你可以將箭頭函數(shù)設(shè)置為 class fields
或 arrow function methods
如下,你可以將 handleClick
重新定義為一個(gè) arrow function method
,來(lái)修復(fù)第一個(gè) example
中的 bug
class Button extends React.Component {
render() {
return (
<button onClick={this.handleClick} style={this.state}>
Set background to red
</button>
);
}
// Note: this syntax is not yet part of JavaScript proper, but is slated
// for inclusion in the next version. It should already work with Babel.
handleClick = () => {
this.setState({ backgroundColor: "red" });
};
}
總結(jié)
- 如果
環(huán)境支持
箭頭函數(shù),那么鼓勵(lì)使用 - 盡量避免對(duì)
React 組件
使用箭頭函數(shù),它會(huì)使調(diào)試變的困難 - 如果有需要,可以在
render
中使用箭頭函數(shù) - 為
性能
著想,避免在render
中使用大量函數(shù)