前言,起因在於今日同事問起,發現不能很好的解釋這個問題,所以自己下來重新屢了一下思路,記錄一下。
一、什麼是箭頭函數,以及爲什麼React裏要用箭頭函數
1. 下面這兩個函數相同。只是react組件化,不支持在組建內部寫function,所以現在用箭頭函數代替js裏的寫法
// 傳參寫法
// 原生js寫法
function test(params) {
console.log('this = ',this)
}
<div onClick={test(123)}></div>
//等價於下面react寫法
test2 = param => () => {
console.log('param = ',param)
}
<div onClick={this.test2(123)}></div>
//不傳參寫法
function test(){} <=> test = () => {}
2. 你肯定會繼續問,那如果只是替換原來的function寫法, 直接在react裏寫
<div onClick={test(123)}></div>
爲什麼要變成 this.test(123) 呢?
這是因爲 在使用ES6 classes或者純函數時,React不會自動綁定this
到當前組件上,需要手動實現this
的綁定。
如果在React裏繼續 test(123),此時test的對象指向的是window,而不是改組建內部,所以會是undefined,這個時候,編譯器檢測到你onClick 綁定了一個 undefined, 所以會報錯。
以上,按照我的思路,首先,你要了解箭頭函數其實是等價替換原有js的函數寫法,其次,比原有寫法多寫this是因爲react不會自動綁定this到當前組建。
二、你還有疑惑嗎
如果我們一開始不知道箭頭函數等價替換了function函數,我們就很容易在React裏把函數寫成下面這個樣子
test(param){
console.log(param);
}
<div onClick={this.test(123)}></div>
期望的效果是,點擊一次這個div,就打印一次傳入的參數123,但是,你發現,只在頁面開始渲染的時候打印了函數,而點擊的時候沒有反應。 這是爲什麼呢?
一開始會打印,是因爲頁面在渲染的時候,把this.test()當成一個函數預執行,所以一開始打印123,而這個函數返回的是undefined。所以你點擊的時候,不會有輸出。此時你的 onClick = undefined;
那如果我是變態一點,給這個函數加返回值
test(param){
console.log(param);
return param
}
<div onClick={this.test(123)}></div>
會發生什麼呢? 答案是:會報錯。因爲這個時候 onClick = 123; 不是一個函數,所以報錯。
三、ES6爲什麼要引入箭頭函數呢?
這裏直接用一下廖雪峯老師的例子。
接上,如果沒有箭頭函數,我們需要用hack的寫法去解決this作用域的問題。
var obj = {
birth: 1990,
getAge: function () {
let that = this;
var b = this.birth; // 1990
var fn = function () {
return new Date().getFullYear() - that.birth; // 此時that指向當前作用域
};
return fn();
}
};
obj.getAge() // 輸出 29 上面輸出25是因爲廖老師寫這篇文章的時候是15年,現在19年啦
四、React裏爲什麼要bind一下呢?
理由同上面 (一.2) 裏提過的,react不會自動綁定函數。比如你可能會這樣寫
test(){
console.log('123');
}
<div onClick={this.test}></div>
你發現每次點擊,確實會打印123,但是你並沒有按照箭頭函數的形式寫,你可能會覺得,這樣也能用,但是,如果你試着打印一下。
constructor(props) {
super(props);
this.state = {
visible: true,
}
}
test(){
console.log(this.state.visible);
}
你會發現打印的是undefined。這就是因爲不用箭頭函數,組件裏的函數不會自動綁定this,這個時候,你需要在constructor裏綁定this。
constructor(props) {
super(props);
this.state = {
visible: true,
}
this.test = this.test.bind(this);
}
test(){
console.log(this.state.visible);
}
這樣每次點擊,就可以打印出來visible的值了。但這種寫法有一種缺陷,就是不能傳參(可能是我目前沒了解到這種寫法傳參的方法)
補一個關於函數和方法的定義
函數(function): 函數是帶有名稱(named)和參數的JavaScript代碼段,可以一次定義多次調用。
方法(method): 當將函數和對象合寫在一起時,函數就變成了 "方法"(method)// 當函數賦值給對象的屬性,我們稱爲"方法"
也就是函數和方法本質上是一樣的,只不過方法是函數的特例,是將函數賦值給了對象。
完結。關於箭頭函數和React裏的使用的原因,以上就是我自己的看法,如果哪裏說的不對,請大家指出來,共同進步。最近無時無刻不在感覺自己知識的不牢固。還是要踏實學習,勤思考纔行..