淺談react 中的 this 指向

前言 最近在做一個(gè)項(xiàng)目的時(shí)候 關(guān)于class方法中 this 指向以及 外置prototype 的 this 指向 引發(fā)了我的思考棒坏!


image.png

ES6原生class

我們假設(shè) A 為 react B 為 我們創(chuàng)建的類 class B extends React.component{}

   class A {
    constructor() {
      this.x = 1;
    }
  }
  class B extends A {
    constructor() {
      super();
      this.x = 2;
      console.log('=====');
      console.log(this);    // B
      console.log(this.x);  // 2
      console.log(super.x); // undefined
      this.getme = this.getme.bind(this)
    }
    getName(){
      console.log('getName');
      console.log(this.x); // B
      let m = this.getme
      m()
    }
    getme(){
      console.log('getme');
      console.log(this.x); // B
    }
  }
  // 類轉(zhuǎn)化為 es5的寫法如下:
  function Es5B() {
    this.x = 2
  }
  Es5B.prototype.getName = function () {
    console.log(this);
    console.log('getName');
    console.log(this.x);
  }

  let b = new B();
  b.getName()

  let esb = new Es5B()
  esb.getName()

打印結(jié)果

image.png

react 高階 api => createElement

https://react.docschina.org/docs/react-without-jsx.html

jsx 語法

class Hello extends React.Component {
  render() {
    return <div>Hello {this.props.toWhat}</div>;
  }
}

ReactDOM.render(
  <Hello toWhat="World" />,
  document.getElementById('root')
);

編譯成下面這段代碼

class Hello extends React.Component {
  render() {
    return React.createElement('div', null, `Hello ${this.props.toWhat}`);
  }
}

ReactDOM.render(
  React.createElement(Hello, {toWhat: 'World'}, null),
  document.getElementById('root')
);

看我們最初的那一段代碼

 // 如果我們將 constructor 中的那個(gè) bind 去掉之后
 // this.getme = this.getme.bind(this)
 // 執(zhí)行到這里  this的指向就變化了
 let m = this.getme
 m() // 此時(shí) this 變化為 undefined

將方法進(jìn)行賦值之后,丟失了上下文,導(dǎo)致 this 變成 undefined 农猬, this之所以沒有變?yōu)閣indow 是因?yàn)轭惵暶骱皖惐磉_(dá)式的主體以 嚴(yán)格模式 執(zhí)行却音,主要包括構(gòu)造函數(shù)改抡、靜態(tài)方法和原型方法。Getter 和 setter 函數(shù)也在嚴(yán)格模式下執(zhí)行系瓢。

ES6class 注意點(diǎn)

譯文
為什么需要在 React 類組件中為事件處理程序綁定 this

未解之謎 原生 class 中 如果方法改為箭頭函數(shù)這種形式就會(huì)報(bào)錯(cuò) 但是在 react 的 class 中 是可以正常渲染的

 class A {
    constructor() {
      this.x = 1;
    }
  }
  class B extends A {
    constructor() {
      super();
      this.x = 2;
    }
    getme=()=>{         // 這里會(huì)報(bào)錯(cuò)誤
      console.log('getme');
      console.log(this.x); 
    }
    getName(){
      console.log('getName');
      console.log(this.x); 
      let m = this.getme
      m()
    }
  }
  
  let b = new B();
  b.getName()

內(nèi)置箭頭函數(shù)與外置箭頭函數(shù)是有區(qū)別的

class B extends A {
  constructor() {
    super();
    this.x = 2
  }
  getName(){
    console.log('getName');
    console.log(this.x); // B
    let m = this.getme
    m()
  }
}

  B.prototype.getme =  ()=> {
    console.log('getme');
    console.log(this);
    /*
     箭頭函數(shù)的 this 指向定義時(shí)所在對(duì)象 定義的環(huán)境在 window
     此時(shí) this 指向 window
     如果是 react 創(chuàng)建的組件  此時(shí) this指向和類之外的 this 是一致的 (但不是 window)
     如果prototype上掛載方法的時(shí)候 強(qiáng)烈建議大家用es5的方式就好阿纤!
    */
  }


let b = new B();
b.getName()

react 創(chuàng)建組件(需要綁定 this 和綁定 this 的方法)

export default class ExtendsCompTable extends React.Component {
  constructor (props) {
    super(props)
    this.state  = {
      name: 'react測試this指向'
    }
    this.handler = this.handler.bind(this)
  }

  handler () {
    message.info('點(diǎn)擊了 bindthis),通過 bind 綁定 this')
  }
  renderDom () {
    let { name } = this.state
    return <Button>{name}</Button>
  }
  handlerArrow=()=> {
    console.log(this);
    message.info('點(diǎn)擊了箭頭函數(shù)綁定按鈕,通過箭頭函數(shù)綁定 this')
  }
  handleInnerArrow(){
    console.log(this);
    message.info('點(diǎn)擊了箭頭函數(shù)綁定,通過 bind 綁定 this')
  }
  handleBind(){
    console.log(this);
    message.info('點(diǎn)擊了bind')
  }
  render () {
    return (
      <div>
        <h1>234567890</h1>
        <Button type='primary' onClick={this.handler}>bind(this)</Button>
        {/* 這種直接調(diào)用的方式不需要綁定 this  作為對(duì)象的方法被調(diào)用 this 指向?qū)ο?/}
        {this.renderDom()}   
        {/* 這種  handlerArrow=()=> {...}的形式  雖然可以用 但是不太建議*/}
        <Button type='primary' onClick={this.handlerArrow}>箭頭函數(shù)綁定</Button>
        <Button type='primary' onClick={() => {
          this.handleInnerArrow()
        }}>點(diǎn)擊觸發(fā)方法</Button>
        <Button type='primary' onClick={this.handleBind.bind(this)}>bind</Button>
        <Table columns={columns} dataSource={data} />
      </div>
    )
  }
}

箭頭函數(shù) ()=>

  • 函數(shù)體內(nèi)的this對(duì)象,就是定義時(shí)所在的對(duì)象夷陋,而不是使用時(shí)所在的對(duì)象欠拾,this是繼承自父執(zhí)行上下文R刃俊!中的this

    var x=11;
    var obj={
      x:22,
      say:function(){
        console.log(this.x)
      }
    }
    obj.say(); // 22
    
    var x=11;
    var obj={
     x:22,
     say:()=>{
       console.log(this.x);
     }
    }
    obj.say();// 11
    
    var a=11
    function test1(){
      this.a=22;
      let b=function(){
        console.log(this.a);
      };
      b();
    }
    var x=new test1(); // 11
    
    var x=11;
    var obj={
     x:22,
     say:()=>{
       console.log(this.x);
     }
    }
    obj.say(); // 22 
    
  • 箭頭函數(shù)中的 this 對(duì)象指向是固定的

  • 不可以當(dāng)作構(gòu)造函數(shù)藐窄,也就是說资昧,不可以使用new命令,否則會(huì)拋出一個(gè)錯(cuò)誤

bind

無論是 call() 也好荆忍, apply() 也好格带,都是立馬就調(diào)用了對(duì)應(yīng)的函數(shù),而 bind() 不會(huì)刹枉, bind() 會(huì)生成一個(gè)新的函數(shù)叽唱,bind() 函數(shù)的參數(shù)跟 call() 一致,第一個(gè)參數(shù)也是綁定 this 的值微宝,后面接受傳遞給函數(shù)的不定參數(shù)尔觉。 bind() 生成的新函數(shù)返回后,你想什么時(shí)候調(diào)就什么時(shí)候調(diào)

var m = {    
    "x" : 1 
}; 
function foo(y) { 
    alert(this.x + y); 
} 
foo.apply(m, [5]); 
foo.call(m, 5); 
var foo1 = foo.bind(m, 5); 
foo1();
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末芥吟,一起剝皮案震驚了整個(gè)濱河市侦铜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌钟鸵,老刑警劉巖钉稍,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異棺耍,居然都是意外死亡贡未,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門蒙袍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來俊卤,“玉大人,你說我怎么就攤上這事害幅∠校” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵以现,是天一觀的道長狠怨。 經(jīng)常有香客問我,道長邑遏,這世上最難降的妖魔是什么佣赖? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮记盒,結(jié)果婚禮上憎蛤,老公的妹妹穿的比我還像新娘。我一直安慰自己纪吮,他們只是感情好俩檬,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布栏豺。 她就那樣靜靜地躺著,像睡著了一般豆胸。 火紅的嫁衣襯著肌膚如雪奥洼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天晚胡,我揣著相機(jī)與錄音灵奖,去河邊找鬼。 笑死估盘,一個(gè)胖子當(dāng)著我的面吹牛瓷患,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播遣妥,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼擅编,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了箫踩?” 一聲冷哼從身側(cè)響起爱态,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎境钟,沒想到半個(gè)月后锦担,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡慨削,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年洞渔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缚态。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡磁椒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出玫芦,到底是詐尸還是另有隱情浆熔,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布姨俩,位于F島的核電站蘸拔,受9級(jí)特大地震影響师郑,放射性物質(zhì)發(fā)生泄漏环葵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一宝冕、第九天 我趴在偏房一處隱蔽的房頂上張望张遭。 院中可真熱鬧,春花似錦地梨、人聲如沸菊卷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽洁闰。三九已至歉甚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間扑眉,已是汗流浹背纸泄。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留腰素,地道東北人聘裁。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像弓千,于是被迫代替她去往敵國和親衡便。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • JavaScript中的this指向問題有很多博客在解釋洋访,仍然有很多人問镣陕。上周我們的開發(fā)團(tuán)隊(duì)連續(xù)兩個(gè)人遇到相關(guān)問題...
    一個(gè)敲代碼的前端妹子閱讀 653評(píng)論 0 5
  • 葡萄藤PPT JS中this的指向 大家好,我是IT修真院鄭州分院第6期的學(xué)員王棟姻政,一枚正直茁彭、純潔、善良的前端程序...
    17064閱讀 627評(píng)論 0 2
  • 40扶歪、React 什么是React理肺?React 是一個(gè)用于構(gòu)建用戶界面的框架(采用的是MVC模式):集中處理VIE...
    萌妹撒閱讀 1,017評(píng)論 0 1
  • 1、吳伯凡老師講理智善镰、欲望和恐懼是認(rèn)知的三元素妹萨,或者說是認(rèn)知三原色。這三樣?xùn)|西互相作用在不同的情況之下都在不停的你...
    第二夢(mèng)想閱讀 264評(píng)論 0 0
  • 你欲想潛入我的心扉 窺探你在我心中的地位炫欺。 但你四顧半天乎完,只發(fā)現(xiàn)這里 是一片空白。 你找到一個(gè)和你一模一樣的聲音品洛。...
    伊洋Lyon閱讀 217評(píng)論 0 0