函數作為React組件的方法時, 箭頭函數和普通函數的區別是什麼?
// React
class Foo extends React.Component{
a(){
console.log(1)
}a=()=&>{
console.log(1)
}}
這兩種有什麼區別
很顯然第一個寫法是非法的。題目標籤裡面有 React, 所以且認為這段代碼是題主在 React 組件(ES6 Class)中截取出來的一部分。
首先是希望題主(以及眾多的其他題主)注意提問姿勢,不要惜墨如金藏頭藏尾,叫別人去猜你要問什麼。
那麼這個問題的完整描述應該是:
class App extends Component {
a() {
console.log(1)
}
a = () =&> {
console.log(1)
}
}
裡面的兩個 a 的定義有什麼區別?
第一個 a 不必說,是原型方法的定義。寬鬆模式下對應 ES5 就是
App.prototype.a = function() {}
第二個是 Stage 2 Public Class Fields 裡面的寫法,babel 下需要用 Class properties transform Plugin 進行轉義。相當於:
class App extends Component {
constructor (...args) {
super(...args)
this.a = () =&> {
console.log(1)
}
}
}
為什麼需要第二種寫法?
在 React 裡面,要將類的原型方法通過 props 傳給子組件,傳統寫法需要 bind(this),否則方法執行時 this 會找不到:
&
或者
&
這種寫法難看不說,還會對 React 組件的 shouldComponentUpdate 優化造成影響。
這是因為 React 提供了 shouldComponentUpdate 讓開發者能夠控制避免不必要的 render,還提供了在 shouldComponentUpdate 自動進行 Shallow Compare 的 React.PureComponent, 繼承自 PureComponent 的組件只要 props 和 state 中的值不變,組件就不會重新 render。
然而如果用了 bind this,每次父組件渲染,傳給子組件的 props.onClick 都會變,PureComponent 的 Shallow Compare 基本上就失效了,除非你手動實現 shouldComponentUpdate.
使用 Public Class Fields 的這種寫法,就解決了這個問題。另外還有其他若干種辦法,比如先定義原型方法,然後在 constructor 裡面 bind 一遍;或者使用 decorator 進行 bind 等:
class A {
constructor() {
this.a = this.a.bind(this)
}
a() {}
// or
@bindthis
b() {}
}
第一種是對象屬性的簡潔賦值方法。不可以直接定義。只是一種簡潔寫法。並不是箭頭函數。this由"調用"該函數的對象來決定。與一般在對象中定義的函數相同。只是簡潔寫法。
var obj = {
a(){
console.log(this)
}
}
//等同於
var obj = {
a: function a() {
console.log(this)
}
}
obj.a(); //obj
var b = obj.a;
b(); //Window
第二種才是箭頭函數。箭頭函數除了代碼少。與普通函數最大的不同就是。this是由聲明該函數時候定義的。一般是隱性定義為聲明該函數時的作用域this。
var a = ()=&>{
console.log(this)
}
//等同於
var a = function(){
console.log(this)
}.bind(this);
a(); //Window
var b = function(){
console.log(this)
};
b(); //Window
var obj = { a,b };
obj.a(); //Window
obj.b(); //obj
第一種是ES6新增的對象方法的簡寫形式第二種才屬於function聲明函數時的簡寫形式
箭頭函數最大的作用是使得this從正常情況下的動態作用域(根據運行位置確定值)變成了靜態作用域(根據定義位置確定值,也就是詞法作用域).
然而你這個函數裡面沒有this,所以跟一般函數沒有區別.
read this doc:
Handling Events - React
箭頭函數主要解決了this的綁定問題,傳統的function存在一個this綁定的問題(this綁定運行時的環境,嚴格模式下可能會導致this取值undefined),而箭頭函數能夠使this綁定定義時環境
推薦閱讀:
※如何實現 Babel 編譯器?
※使用ES6 Module如何處理模塊按需載入 (lazyload)?
※瀏覽器直接支持ES6了,還需要編譯么?
TAG:JavaScript | ECMAScript2015 | React | ReactNative |