問題一:為啥要用bind 和 箭頭函數
剛接觸React,基本上都會遇到一個問題:就是在事件處理函數里面用到了this,但是 這個this是undefined,導致報錯。
然后這個問題的原因,常見說法是:“React事件處理函數是沒有默認綁定this的”,雖然沒有錯,但是沒有get到真正的點。
原因:
首先,這是 JavaScript 函數和this工作原理導致的,並不是React的問題,事件處理的那個 props——onClick 接收到了函數,卻不知道執行上下文
this是當前函數運行所在的環境,也就是總是指向函數運行所在的那個對象。
解決方案:
1、使用bind綁定
2、使用箭頭函數。
先看看關於this的一個例子
1 var obj = { 2 foo: function() { 3 console.log(this) 4 } 5 } 6 7 var foo = obj.foo 8 9 obj.foo() // 打印結果是 obj對象 10 foo() // 打印結果是 undefined
再看一個用 class 模擬一個和React相似的例子:
1 let onClick = null 2 3 class CustomReact { 4 handleClick() { 5 console.log(this) 6 } 7 render() { 8 onClick = this.handleClick 9 } 10 } 11 var c = new CustomReact() 12 c.render() 13 14 onClick() // 打印出來的是 undefined
因為在賦值的時候,丟失了它的 執行上下文,只賦值過去了一個普通函數。
所以我們只有“包裝”一個含有執行上下文的函數,然后賦值給新變量,那么這個變量執行的時候就能找到它的執行上下文。
“包裝”的方法就有 bind 和 箭頭函數
然后用處理React的方法,用bind稍作修改
/* 把 onClick = this.handleClick * 改成 onClick = this.handleClick.bind(this) * 或者 把 handleClick 改為 handleClick = () => {} * 然后再 執行 onClick ,打印的就會是CustomReact 對象 */
問題二: class 中,handleClick() {} 和 handleClick = () => {} 的區別
區別一:前者是方法的簡寫,所以還是function函數,后者是箭頭函數
區別二:前者是原型方法,后者是實例方法。
1 class Test { 2 instanceFunc = () => {} // 實例方法 3 4 protoFunc() {} // 原型方法。這是ES6對象方法的簡寫 5 6 } 7 8 // 上面代碼等同於 9 10 function Test() { 11 this.instanceFunc = function () {} 12 } 13 14 Test.prototype = { 15 constructor: Test 16 protoFunc: function() {} 17 }
問題三:在render 中綁定 this 和 在外面綁定的區別?
在 render 中綁定this的時候,不管bind還是箭頭函數都會新創建一個函數,這會可能會破壞它本身嚴格比較的優化
相比較於這兩種,更推薦使用下面兩種用法
1、
this.handleClick = this.handleClick.bind(this)
.....
onClick={this.handleClick}
2、
handleClick = () => {}
....
onClickonClick={this.handleClick}