溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何解決js中this指向問題

發(fā)布時(shí)間:2021-09-17 10:38:49 來源:億速云 閱讀:189 作者:柒染 欄目:web開發(fā)

本篇文章給大家分享的是有關(guān)如何解決js中this指向問題,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

如何解決js中this指向問題

JS中this指向問題

相信我,只要記住本文的7步口訣,就能徹底掌握 JS 中的this指向。

先念口訣:箭頭函數(shù)、new、bind、apply 和 call、歐比屆點(diǎn)(obj.)、直接調(diào)用、不在函數(shù)里。

按照口訣的順序,只要滿足前面某個(gè)場(chǎng)景,就可以確定this指向了。

接下來按照口訣順序?qū)λ鼈冞M(jìn)行詳解,文中示例代碼都運(yùn)行在ChromeConsole控制臺(tái)中。

文末有精心準(zhǔn)備的練習(xí)題,用于檢驗(yàn)學(xué)習(xí)成果,別忘了試試~

1. 箭頭函數(shù)

箭頭函數(shù)排在第一個(gè)是因?yàn)樗?code>this不會(huì)被改變,所以只要當(dāng)前函數(shù)是箭頭函數(shù),那么就不用再看其他規(guī)則了。

箭頭函數(shù)的this是在創(chuàng)建它時(shí)外層this的指向。這里的重點(diǎn)有兩個(gè):

1、創(chuàng)建箭頭函數(shù)時(shí),就已經(jīng)確定了它的this指向。

2、箭頭函數(shù)內(nèi)的this指向外層的this。

所以要知道箭頭函數(shù)的this就得先知道外層this的指向,需要繼續(xù)在外層應(yīng)用七步口訣。

2. new

當(dāng)使用 new 關(guān)鍵字調(diào)用函數(shù)時(shí),函數(shù)中的 this 一定是 JS 創(chuàng)建的新對(duì)象。

讀者可能會(huì)有疑問,“如果使用new關(guān)鍵調(diào)用箭頭函數(shù),是不是箭頭函數(shù)的this就會(huì)被修改呢?”。

我們?cè)诳刂婆_(tái)試一下。

func = () => {} 
new func() // throw error

如何解決js中this指向問題

從控制臺(tái)中可以看出,箭頭函數(shù)不能當(dāng)做構(gòu)造函數(shù),所以不能與new一起執(zhí)行。

3. bind

bind 是指 Function.prototype.bind() 詳細(xì)地址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

多次 bind 時(shí)只認(rèn)第一次 bind 的值

易錯(cuò)點(diǎn)

function func() {
  console.log(this)
}

func.bind(1).bind(2)() // 1

箭頭函數(shù)中 this 不會(huì)被修改

func = () => {
  // 這里 this 指向取決于外層 this,參考口訣 7 「不在函數(shù)里」
  console.log(this)
}

func.bind(1)() // Window,口訣 1 優(yōu)先

bind 與 new

易錯(cuò)點(diǎn)

function func() {
  console.log(this, this.__proto__ === func.prototype)
}

boundFunc = func.bind(1)
new boundFunc() // Object true,口訣 2 優(yōu)先

4. apply 和 call

apply()call()的第一個(gè)參數(shù)都是this,區(qū)別在于通過apply調(diào)用時(shí)實(shí)參是放到數(shù)組中的,而通過call調(diào)用時(shí)實(shí)參是逗號(hào)分隔的。

箭頭函數(shù)中 this 不會(huì)被修改

易錯(cuò)點(diǎn)

func = () => {
  // 這里 this 指向取決于外層 this,參考口訣 7 「不在函數(shù)里」
  console.log(this)
}

func.apply(1) // Window,口訣 1 優(yōu)先

bind 函數(shù)中 this 不會(huì)被修改

易錯(cuò)點(diǎn)

function func() {
  console.log(this)
}

boundFunc = func.bind(1)
boundFunc.apply(2) // 1,口訣 3 優(yōu)先

5. 歐比屆點(diǎn)(obj.)

function func() {
  console.log(this.x)
}

obj = { x: 1 }
obj.func = func
obj.func() // 1

這里就不用代碼例證箭頭函數(shù)和 bind 函數(shù)的優(yōu)先級(jí)更高了,有興趣可自行嘗試吧。

6. 直接調(diào)用

在函數(shù)不滿足前面的場(chǎng)景,被直接調(diào)用時(shí),this將指向全局對(duì)象。在瀏覽器環(huán)境中全局對(duì)象是Window,在Node.js環(huán)境中是Global。

先來個(gè)簡(jiǎn)單的例子。

function func() {
  console.log(this)
}

func() // Window

來一個(gè)復(fù)雜的例子,外層的outerFunc就起個(gè)迷惑目的。

function outerFunc() {
  console.log(this) // { x: 1 }

  function func() {
    console.log(this) // Window
  }

  func()
}

outerFunc.bind({ x: 1 })()

7. 不在函數(shù)里

不在函數(shù)中的場(chǎng)景,可分為瀏覽器的<script />標(biāo)簽里,或Node.js的模塊文件里。

1、在<script />標(biāo)簽里,this指向Window。

2、在Node.js的模塊文件里,this指向Module的默認(rèn)導(dǎo)出對(duì)象,也就是module.exports。

非嚴(yán)格模式

嚴(yán)格模式是在ES5提出的。在ES5規(guī)范之前,也就是非嚴(yán)格模式下,this不能是undefinednull。所以**在非嚴(yán)格模式下,通過上面七步口訣,如果得出this指向是undefinednull,那么this會(huì)指向全局對(duì)象。**在瀏覽器環(huán)境中全局對(duì)象是Window,在Node.js環(huán)境中是Global。

例如下面的代碼,在非嚴(yán)格模式下,this都指向全局對(duì)象。

function a() {
  console.log("function a:", this)
  ;(() => {
    console.log("arrow function: ", this)
  })()
}

a()

a.bind(null)()

a.bind(undefined)()

a.bind().bind(2)()

a.apply()

非嚴(yán)格模式下執(zhí)行結(jié)果為:

如何解決js中this指向問題

在嚴(yán)格模式下,執(zhí)行同樣的代碼進(jìn)行對(duì)比。記住要一次性將所有代碼復(fù)制粘貼到控制臺(tái)中,才能運(yùn)行在嚴(yán)格模式下(因?yàn)榈谝恍?"use strict" 才會(huì)對(duì)后面的代碼生效)。

"use strict"

function a() {
  console.log("function a:", this)
  ;(() => {
    console.log("arrow function: ", this)
  })()
}

a()

a.bind(null)()

a.bind(undefined)()

a.bind().bind(2)()

a.apply()

嚴(yán)格模式下執(zhí)行結(jié)果為:

如何解決js中this指向問題

七步口訣在嚴(yán)格模式下和非嚴(yán)格模式下都是完備的,只是在非嚴(yán)格模式下nullundefined會(huì)被轉(zhuǎn)換為全局對(duì)象。所以我沒有將這點(diǎn)列入口訣中。

做題復(fù)習(xí)

先背誦口訣再做題,“箭頭函數(shù)、newbind、applycall、歐比屆點(diǎn)(obj.)、直接調(diào)用、不在函數(shù)里”。

1. 下面代碼執(zhí)行后,func.count 值為多少?

function func(num) {
  this.count++
}

func.count = 0
func(1)

答案

func.count值為 0。

按照口訣,func()調(diào)用時(shí)屬于第 6 類「直接調(diào)用」。在非嚴(yán)格模式下,this指向全局對(duì)象。thisfunc 一點(diǎn)關(guān)系都沒有,所以 func.count保持不變so easy。

2. 以下箭頭函數(shù)中 this 指向誰呢?

obj = {
  func() {
    const arrowFunc = () => {
      console.log(this._name)
    }

    return arrowFunc
  },

  _name: "obj",
}

obj.func()()

func = obj.func
func()()

obj.func.bind({ _name: "newObj" })()()

obj.func.bind()()()

obj.func.bind({ _name: "bindObj" }).apply({ _name: "applyObj" })()

答案

// obj
// undefined
// newObj
// undefined
// bindObj

是不是很簡(jiǎn)單,你學(xué)廢了嗎?

以上就是如何解決js中this指向問題,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI