從 React 綁定 this让虐,看 JS 語言發(fā)展和框架設計

react

在 javascript 語言中,關于 this 這個關鍵字的行為一直以來困擾著一代又一代初級開發(fā)者黑滴。同時 this憨募,也充分反應了 javascript 的詭異與靈活。

但是請別誤會袁辈,這篇文章并不會對 this 的特征進行全方位講解菜谣,因為這些內容都可以在各種前端書籍中找到答案。這里晚缩,我試圖結合 React 事件處理函數關于 this 綁定的演化史尾膊,談一談這個框架設計以及 javascript 語言在這一細節(jié)上的進步和完善。同時對比 this 綁定的不同方案荞彼,讓大家對 React 冈敛、ES next 有一個更清晰的認識。

React 處理 this 上下文環(huán)境已經有至少五年歷史了鸣皂。五年期間抓谴,方案輩出暮蹂,我們先來總結一下。

方法一:React.createClass 自動綁定

React 中創(chuàng)建組件的方式已經很多癌压,比較古老的諸如 React.createClass 應該很多人并不陌生椎侠。當然,從 React 0.13 開始措拇,可以使用 ES6 Class 代替 React.createClass 了我纪,這應該是今后推薦的方法。
但是需要知道丐吓,React.createClass 創(chuàng)建的組件浅悉,可以自動綁定 this。也就是說券犁,this 這個關鍵字會自動綁定在組件實例上面术健。

// This magically works with React.createClass
// because `this` is bound for you.
onChange = {this.handleChange}

當然很遺憾,對于組件的創(chuàng)建粘衬,官方已經推薦使用 class 聲明組件或使用 functional 無狀態(tài)組件:

Later, classes were added to the language as part of ES2015, so we added the ability to create React components using JavaScript classes. Along with functional components, JavaScript classes are now the preferred way to create components in React.
For your existing createClass components, we recommend that you migrate them to JavaScript classes.

我認為荞估,這其實是 React 框架本身的自我完善和對未來的迎合,是框架和語言發(fā)展的大勢所趨稚新。


方法二:渲染時綁定

通過前文勘伺,我們知道最傳統(tǒng)的組件創(chuàng)建方式不會有 this 綁定的困擾。接下來褂删,我們假定所有的組件都采取 ES6 classes 方式聲明飞醉。這種情況下,this 無法自動綁定屯阀。一個常見的解決方案便是:

onChange = {this.handleChange.bind(this)}

這種方法簡明扼要缅帘,但是有一個潛在的性能問題:當組件每次重新渲染時,都會有一個新的函數創(chuàng)建难衰。OMG! 這聽上去貌似是一個很大的問題钦无,但是其實在真正的開發(fā)場景中,由此引發(fā)的性能問題往往不值一提(除非是大型組件消費類應用或游戲)盖袭。


方法三:箭頭函數綁定

這種方法其實和第二種類似失暂,拜 ES6 箭頭函數所賜,我們可以隱式綁定 this:

onChange = {e => this.handleChange(e)}

當然苍凛,也與第二種方法一樣趣席,它同樣存在潛在的性能問題
下面將要介紹的兩種方法醇蝴,可以有效規(guī)避不必要的性能消耗宣肚,請繼續(xù)閱讀。


方法四:Constructor 內綁定

constructor 方法是類的默認方法悠栓,通過new命令生成對象實例時霉涨,自動調用該方法按价。

所以我們可以:

constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
}

這種方式往往被推薦為“最佳實踐”,也是筆者最為常用的方法笙瑟。

但是就個人習慣而言楼镐,我認為與前兩種方法相比,constructor 內綁定在可讀性和可維護性上也許有些欠缺往枷。
同時框产,我們知道在 constructor 聲明的方法不會存在實例的原型上,而屬于實例本身的方法错洁。每個實例都有同樣一個 handleChange秉宿,這本身也是一種重復和浪費。

如果你對 ES next 一直抱有開放的思想屯碴,且能夠使用 stage-2 的特性描睦,不妨嘗試一下最后一種方案。


方法五:Class 屬性中使用 = 和箭頭函數

這個方法依賴于 ES next 的新特性导而,請參考 tc 39: Public Class Fields

handleChange = () => {
      // call this function from render 
      // and this.whatever in here works fine.
};

我們來總結一下這種方式的優(yōu)點:

  • 使用箭頭函數忱叭,有效綁定了 this;
  • 沒有第二種方法和第三種方法的潛在性能問題今艺;
  • 避免了方法四的組件實例重復問題韵丑;
  • 我們可以直接從 ES5 createClass 重構得來。


總結

本文在對比 React 綁定 this 的五種方法的同時洼滚,也由遠及近了解了 javascript 語言的發(fā)展:從 ES5 的 bind埂息, 到 ES6 的箭頭函數,再到 ES next 對 class 的改進遥巴。

React 作為蓬勃發(fā)展的框架也同樣在與時具進,不斷完善享幽,結合語言特性的發(fā)展不斷調整著自身铲掐。

最后,我們通過這張圖片來完整回顧:

各種方式邏輯

本文參考了 Cory House 的文章:5 Approaches for Handling this值桩,并在此基礎上進行延伸摆霉。



我的其他一些關于 React 文章:

Happy Coding!

PS: 作者Github倉庫,歡迎通過代碼各種形式交流奔坟。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末携栋,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子咳秉,更是在濱河造成了極大的恐慌婉支,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件澜建,死亡現場離奇詭異向挖,居然都是意外死亡蝌以,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門何之,熙熙樓的掌柜王于貴愁眉苦臉地迎上來跟畅,“玉大人,你說我怎么就攤上這事溶推』布” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵蒜危,是天一觀的道長庇忌。 經常有香客問我,道長舰褪,這世上最難降的妖魔是什么皆疹? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮占拍,結果婚禮上略就,老公的妹妹穿的比我還像新娘。我一直安慰自己晃酒,他們只是感情好表牢,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著贝次,像睡著了一般崔兴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蛔翅,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天敲茄,我揣著相機與錄音,去河邊找鬼山析。 笑死堰燎,一個胖子當著我的面吹牛,可吹牛的內容都是我干的笋轨。 我是一名探鬼主播秆剪,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼爵政!你這毒婦竟也來了仅讽?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤钾挟,失蹤者是張志新(化名)和其女友劉穎洁灵,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體等龙,經...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡处渣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年伶贰,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片罐栈。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡黍衙,死狀恐怖,靈堂內的尸體忽然破棺而出荠诬,到底是詐尸還是另有隱情琅翻,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布柑贞,位于F島的核電站方椎,受9級特大地震影響,放射性物質發(fā)生泄漏钧嘶。R本人自食惡果不足惜棠众,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望有决。 院中可真熱鬧闸拿,春花似錦、人聲如沸书幕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽台汇。三九已至苛骨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間苟呐,已是汗流浹背痒芝。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留掠抬,地道東北人吼野。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像两波,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子闷哆,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內容

  • GUIDS 第一章 為什么使用React腰奋? React 一個提供了用戶接口的JavaScript庫。 誕生于Fac...
    jplyue閱讀 3,536評論 1 11
  • 原教程內容詳見精益 React 學習指南抱怔,這只是我在學習過程中的一些閱讀筆記劣坊,個人覺得該教程講解深入淺出,比目前大...
    leonaxiong閱讀 2,834評論 1 18
  • React創(chuàng)建組件的三種方式及其區(qū)別 React推出后屈留,出于不同的原因先后出現三種定義react組件的方式局冰,殊途同...
    程序猿吳彥祖閱讀 258評論 0 0
  • 目前测蘑,react組件有三種寫法,分別是es5的createClass寫法康二,es6的class寫法碳胳,以及statel...
    ZoomFunc閱讀 1,654評論 0 1
  • 本筆記基于React官方文檔,當前React版本號為15.4.0沫勿。 1. 安裝 1.1 嘗試 開始之前可以先去co...
    Awey閱讀 7,705評論 14 128