激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服務器之家 - 編程語言 - JavaScript - React - 詳解React中的this指向

詳解React中的this指向

2022-03-10 16:36小林別鬧 React

這篇文章主要介紹了React中的this指向的相關資料,幫助大家更好的理解和學習使用React,感興趣的朋友可以了解下

打算記流水賬一般細數一下 React 中的 this 指向問題,具體流程按事件三要素:起因,經過,結果。哈哈哈哈哈!

起因:

眾所周知,React 的設計是響應式的,使用者無需操縱 DOM,操縱數據,頁面就會渲染更新。

數據一變就更新,是更新所有的 DOM 嗎?當然不是,哪些變了就重新渲染哪些。那就要對數據變化前后的 DOM 進行比較。直接對比真實 DOM 嗎?這樣性能會很低,React 比較的是虛擬 DOM,虛擬 DOM 也是對象,只不過相較真實 DOM而言,少了很多屬性,更“輕”。

如何寫虛擬 DOM 呢?原生JS我們可以使用 document.createElement() 方法,創建節點。React 中也可以通過 React.createElement(component, props, children),但是呢這種寫法遇見多層嵌套,就能讓人眼花繚亂。于是 JSX “橫空出世”,JSX 其實就是,React.createElement 的語法糖,但是我們用起來更加方便,可以直接寫成 <p id="test">hello</p> 這種形式。

但是呢問題又又來了!JSX 語法是不被 webpack 識別的,webpack 默認只能處理 .js 后綴名的文件,所以需要借助 Babel 這個 JavaScript 編譯器,而 babel 開啟了嚴格模式 **

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import React, { Component } from 'react'
 
export default class index extends Component {
    // speak(){
    //     console.log(this)//輸出undefined
    // }
    speak = () => console.log(this)//輸出該組件
    render() {
        return (
            <div>
                <button onClick={this.speak}>按鈕</button>
            </div>
        )
    }
}

this 本質上就是指向它的調用者,this 是在函數運行時才綁定,JS 里邊普通函數都是 window 調用的,所以指向 window,開啟了嚴格模式之后是 undefined。

?
1
2
3
(function(){
    console.log(this)//window
})()

在 JSX 中傳遞的事件不是一個字符串(在原生 JS 的中監聽事件,采用的是回調函數的形式,在Vue中給監聽事件傳遞的是字符串變量),而是一個函數(如上面的:onClick={this.speak}),此時onClick即是中間變量,最終是由React調用該函數,而因為開啟了嚴格模式的緣故,this 是undefined,所以處理函數中的this指向會丟失。

經過:

事實上我們需要的是 this 指向當前實例化對象,無疑會使代碼編寫方便很多。類式組件里邊有兩地方的this恰好指向當前實例化對象。

1.構造函數

類式組件里面的構造器里面的this是指向實例對象的,這是 ES6 類的特性,

眾所周知 Javascript 里面是沒有像 C++,JAVA 里面的的類的概念,ES6 類的實現也是基于原型鏈來實現的,

在 ES6 以前實例化一個對象應該這樣:

?
1
2
3
4
5
6
7
8
9
function Animal(name, age) {
  this.name = name
  this.age = age
}
Animal.prototype.say = function () {
  console.log(this.name)
}
const Dog = new Animal('dog', 3)
Dog.say()  //會在控制臺打印出dog

其中的 new 運算符,先產生了一個空對象 {},然后生成一個 this 指針,將 this 指針指向這個空對象;運行構造函數時,就相當于{}.name=dog,{}.age=3一樣的為這個對象動態添加屬性。最后將這個生成好的對象付給 Dog,

當我們使用 ES6 的 class 來聲明上面這個類的話,代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
class Animal {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  say() {
    console.log(this.name)
  }
}
const Dog = new Animal('dog', 3)
Dog.say()  //會在控制臺打印出dog

類實現和上面應該大差不差,所以this是指向實例對象的。

2.render 函數

render 函數里面的 this,也是指向實例的。為啥呢?

首先 render 方法是在類式組件的原型上邊的,React發現組件是使用類定義的時候,后邊就會 new 出來該類的實例,注意這個實例是 React 幫你 new 出來的,隨后實例調用 render 方法,將虛擬 DOM 轉換為真實 DOM,所以 render 中的this 就是指向實例咯,畢竟是他調用的嘛!,類似的呢,render 是一個生命周期鉤子,那其他的生命周期鉤子里面的 this也是指向實例組件的。

3.bind 和箭頭函數

解決 this 問題呢,要有兩個知識儲

(1)bind
call apply bind 都是定義在函數原型上邊的,用來改變函數 this 指向,傳入的第一個參數是 this,后面的參數就是fun1的參數

區別:

  • call 和 bind 傳給調用的函數是可以傳多個 apply 則是將參數放進一個數組
  • call 和 apply 返回立即執行函數,bind 返回新的函數,bind()() 也是立即執行
  • 使用 bind 綁定 this 后,該函數里面的 this 不能變化了,不論是誰調用
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let aa = {
    fun1: function(a,b){
        console.log(this)
        console.log(a-b);
    }
}       
let bb = {
    fun2: function(a,b){
        console.log(this)
        console.log(a+b);
    }
}
 
aa.fun1.call(bb,11,22);//bb-11
bb.fun2.apply(aa,[11,22]);//aa 33
aa.fun1.bind(bb,11,22)();//bb -11

(2)箭頭函數
箭頭函數:箭頭函數并不會創建自己的執行上下文,所以箭頭函數中的this都是外層的this,會向外作用域中,一層層查找this,直到有 this 的定義

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const A = {
    arrow:() =>{
        console.log(this)//window
    },
    func:function(){
        this.arrow()//window
        console.log(this)//A
        setTimeout(() => {
            console.log(this)//A
        });
    }
}
A.arrow()
A.func()

結果:

解決方法俺會兩,嘿嘿!

方法一:在構造函數中使用bind

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React, { Component } from 'react'
 
export default class index extends Component {
    constructor(){
        super()
        this.speak = this.speak.bind(this)
        /*解決類中的this問題:this.speak = this.speak.bind(this),構造器里面的this默認指向實例對象,
      實例對象通過原型鏈在類的原型上找著fnc函數,通過bind函數將其this指向改為實例對象,并返回一個新的函數
      再將這個新的函數給實例,并取名為fnc*/
    }
    speak(){
        console.log(this)//輸出當前實例對象
    }
    render() {
        return (
            <div>
                <button onClick={this.speak}>按鈕</button>
            </div>
        )
    }
}

方法二:將箭頭函數賦值給類的屬性

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React, { Component } from 'react'
 
export default class index extends Component {
    speak = () =>{
        console.log(this)
    }
    render() {
        return (
            <div>
                <button onClick={this.speak}>按鈕</button>
            </div>
        )
    }
}//需要傳參的話,可以使用函數柯里化的思想

注意:性能存在差異

使用箭頭函數來解決性能會比較低,因為箭頭函數不是方法,它們是匿名函數表達式,所以將它們添加到類中的唯一方法是賦值給屬性。前面介紹ES6的類的時候可以看出來,ES 類以完全不同的方式處理方法和屬性

方法被添加到類的原型中,而不是每個實例定義一次。

類屬性語法是為相同的屬性分配給每一個實例的語法糖,實際上會在 constructor里面這樣實現:

?
1
2
3
4
constructor(){
    super()
    this.speak = () => {console.log(this)}
}

這意味著新實例被創建時,函數就會被重新定義,丟失了JS實例共享原型方法的優勢。而方法一,只是在生成實例時多了一步 bind 操作,在效率與內存占用上都有極大的優勢

以上就是詳解React中的this指向的詳細內容,更多關于React中的this指向的資料請關注服務器之家其它相關文章!

原文鏈接:https://juejin.cn/post/6954636599892279304

延伸 · 閱讀

精彩推薦
  • React使用 React 和 Threejs 創建一個VR全景項目的過程詳解

    使用 React 和 Threejs 創建一個VR全景項目的過程詳解

    這篇文章主要介紹了使用 React 和 Threejs 創建一個VR全景項目的過程詳解,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒...

    Windy Z11122022-02-23
  • ReactReact html中使用react的兩種方式

    React html中使用react的兩種方式

    這篇文章主要介紹了React html中使用react的兩種方式,本文給大家提到了React pwa的配置代碼,給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒...

    愚公搬代碼6372022-02-23
  • React詳解React中的不可變值

    詳解React中的不可變值

    這篇文章主要介紹了React中的不可變值的相關資料,幫助大家更好的理解和學習使用react.js,感興趣的朋友可以了解下...

    一個前端王10622022-02-27
  • React不用一行代碼,搞懂React調度器原理

    不用一行代碼,搞懂React調度器原理

    本文會講解React調度器Scheduler的實現原理。知道你不喜歡看大段的代碼,所以本文沒有一行代碼。文末有Scheduler的源碼地址,感興趣的話可以去看看。...

    魔術師卡頌10582021-12-26
  • React聊一聊我對 React Context 的理解以及應用

    聊一聊我對 React Context 的理解以及應用

    這篇文章主要介紹了聊一聊我對 React Context 的理解以及應用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的...

    張國鈺6582022-02-24
  • React詳解react應用中的DOM DIFF算法

    詳解react應用中的DOM DIFF算法

    這篇文章主要介紹了react應用中的DOM DIFF算法,幫助大家更好的理解和學習使用react,感興趣的朋友可以了解下...

    time_w6302022-02-25
  • ReactReact ref的使用示例

    React ref的使用示例

    這篇文章主要介紹了React ref的使用詳解,幫助大家更好的理解和學習使用React,感興趣的朋友可以了解下...

    陳小瓦8822022-02-25
  • React如何不使用eject修改create-react-app的配置

    如何不使用eject修改create-react-app的配置

    許多剛開始接觸create-react-app框架的同學,不免都會有個疑問:如何在不執行eject操作的同時,修改create-react-app的配置。...

    胡哥有話說6932022-02-28
主站蜘蛛池模板: 狠狠干视频网站 | 色综合视频 | 成人短视频在线播放 | 91精品国产乱码久久桃 | 麻豆视频国产在线观看 | 91短视频在线观看 | 一区二区三区欧美在线 | 精品一区二区三区免费毛片 | 精品一区二区三区在线观看视频 | 91精品国产一区二区三区动漫 | 美女性感毛片 | 黄污免费网站 | 亚洲精品久久久久久久久久久 | 日日狠狠久久偷偷四色综合免费 | 伊人手机在线观看 | 久久福利国产 | 一区二区三视频 | 成人小视频在线播放 | 成人毛片100部 | 中文字幕综合在线观看 | 圆产精品久久久久久久久久久 | 欧美成人一区二区三区电影 | 福利一区二区三区视频在线观看 | 久久国产不卡 | 一级在线观看视频 | 国产精品久久久久久久久久久久久久久 | 国产一级伦理片 | 操操日日 | 美国人成人在线视频 | 国产精品一区二区三区在线播放 | 日韩av电影在线观看 | 日本不卡一区在线观看 | 手机视频在线播放 | 一区二区三区欧美精品 | 爱逼爱操综合网 | 国产一区二区三区视频在线观看 | 高潮激情aaaaa免费看 | 牛牛视频在线 | 奇米888一区二区三区 | 91嫩草丨国产丨精品入口 | 成人一区三区 |