react中的this指向?
import React, { Component } from "react";
class App extends Component {
handleClick(e, arg) {
console.log(e, arg);
}
render() {
this.handleClick();
// 通過bind方法實現,可以傳遞參數
return &;
}
}
this.handleClick.bind(this)這裡的兩個this都指向App的實例對象?
另外能說下this.handleClick();與this.handleClick.bind(this);關於this的區別以及原理嗎?
其實最基本的規則一直都沒有變,通過兩個關鍵點看this的指向:
this出現在哪個由function關鍵字聲明的函數里(即非箭頭函數,可以理解為箭頭函數里的this為一個正常變數)
該函數被誰,以何種方式(指call/apply、還是直接調用、還是把函數當成某個對象的屬性調用)調用,調用時傳入的的參數是啥:
- obj.f
- f.call/bind(obj)
- f()
實際上被誰調用其實並不重要,最重要的是被如何調用
第一個this.handleClick()的this出現在render函數里,所以得看render會如何被調用,很明顯render是被React調用的,所以這取決於React的設置了,明顯React會把this設置為組件實例,完。
後面jsx里的onClick={this.handleClick}如果寫成這樣的話,你要知道this.handleClick傳給了button組件後是丟失了this了的!如下:
var obj = {
f: function(){
console.log(this)
}
}
function foo(f) {
f()
}
foo(obj.f)
上面的代碼中,foo運行時接收到的參數f時,foo是並不知道f是obj的屬性的,也就是常說的丟失了上下文。
而&
這也是為什麼數組對象上的map,filter方法還接收第二個參數的原因,因為萬一你第一個參數傳的是一個從對象上讀出來的函數,而這個函數又依賴於這個對象才能正確行為的話,map如果不把函數的this設置為上下文對象的話,函數就無法正確工作了:
var obj = {
value: 1,
mapper: function()
return this.value
}
}
[1,2,3].map(obj.f);//[undefined*3]
[1,2,3].map(obj.f, obj)//[1,1,1]
而你寫成&
那麼問題又來了,為什麼使用React最早的組件語法,也就是React.createClass又不用這麼指定呢?因為那種寫法里,你傳給createClass的是一個對象,並不是es6這種語言級別自帶的語法。createClass函數可以直接從你傳入的對象中獲得每一個函數,然後幫你bind一下,並bind的最合適的值到this上面。
所有的語法規則都沒有變過,所以說基礎是非常重要的,如果基礎不好,是不是你要背下來各種情況下this的指向?有些人不要總是幻想js沒學好這些框架就能拯救你,不可能的。
那兩個this都是App類的實例,因為所處環境中this就是這個含義。
this.handleClick()是一次函數調用,this.handleClick.bind(this)產生的是一個新的函數,這個函數在被拿來執行就是執行this.handleClick,而且函數體里的this絕對是App類的這個實例。
要用bind方法,是因為單純把this.handleClick作為參數傳遞出去之後,就失去this的環境了,ES6不會自動給成員函數綁定this,只好代碼實現。this 能繞暈好多初學者感覺 this 比 react 還難呢 ~(*?_?)ノ⌒*
es6 中類實例中的所有方法中的 this 都指向其自身,但是如果類實例中的方法被抽離出來就會失去this對實例的指向,這裡的 onClick 最終調用的環境是 window ,而 class 默認嚴格模式,所以 onClick 在運行時會指向 undefined。
而 react 中對此並沒有使用自動綁定策略,所以要麼使用箭頭函數,要麼使用bind函數,不過題主在render中使用bind並不好,因為bind會每次創建一個新的函數,所以建議在 constructor 中進行綁定。
你不知道的JavaScript總結與超越 (上) 附網盤鏈接
同學來我這篇文章打下基礎 看this部分 包你會 看完不會的你來找我
附上解答: 第一個this是render函數自身的this對象,即組件實例,第二個this.handleClick.bind(this)中的bind(this)是綁定規則中的顯式綁定,人為的把handleClick函數中的this對象綁定到外面這個this對象上。
如果我講的這幾句話你聽不懂 那你必須得去看我貼的鏈接了~
如果實在弄不清,寫react有個簡單暴力的方法,即:
在所有生命周期函數上都用普通函數,即綁定this的函數,其他所有函數全部用箭頭函數。
因為實際上react主動調用的是生命周期函數,然後再在裡面調用自定義函數,這些可以自動綁定到this。應該是比較好的實踐。
個人很喜歡用下面的裝飾器來處理class實例方法的this問題:
// 將實例的原型上面所有函數都綁定this
export function bindMethods(oldConstructor) {
const newConstructor: any = function(...args) {
const instance = new oldConstructor(...args);
const prototype = oldConstructor.prototype;
Object.keys(prototype).forEach(key =&> {
if (typeof prototype[key] === "function") {
instance[key] = prototype[key].bind(instance);
}
});
return instance;
};
// 複製構造函數的$inject屬性
Object.assign(newConstructor, oldConstructor);
newConstructor.prototype = oldConstructor.prototype;
return newConstructor;
}
使用的時候,在class前面加上就好啦:
@bindMethods
export class YourComponent {
}
this這玩意在JS裡面就是玄學。很多時候你需要定義一個新的變數用來正確的傳遞this。
推薦閱讀:
※react中出現的"hydrate"這個單詞到底是什麼意思?
※如何看待 BrendanEich、Vjeux 等人就 React Native 的討論?
※這些手機銷售前端頁面用了哪些技術?
※JS 中 var add=function(){} add(a)(b)(c); 是什麼簡寫?
※匿名函數的this指向為什麼是window?