您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關如何解決js中this指向問題,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
相信我,只要記住本文的7步口訣,就能徹底掌握 JS 中的this
指向。
先念口訣:箭頭函數、new、bind、apply 和 call、歐比屆點(obj.)、直接調用、不在函數里。
按照口訣的順序,只要滿足前面某個場景,就可以確定this
指向了。
接下來按照口訣順序對它們進行詳解,文中示例代碼都運行在Chrome
的Console
控制臺中。
文末有精心準備的練習題,用于檢驗學習成果,別忘了試試~
箭頭函數排在第一個是因為它的this
不會被改變,所以只要當前函數是箭頭函數,那么就不用再看其他規則了。
箭頭函數的this
是在創建它時外層this
的指向。這里的重點有兩個:
1、創建箭頭函數時,就已經確定了它的this
指向。
2、箭頭函數內的this
指向外層的this
。
所以要知道箭頭函數的this
就得先知道外層this
的指向,需要繼續在外層應用七步口訣。
當使用 new 關鍵字調用函數時,函數中的 this 一定是 JS 創建的新對象。
讀者可能會有疑問,“如果使用new
關鍵調用箭頭函數,是不是箭頭函數的this
就會被修改呢?”。
我們在控制臺試一下。
func = () => {} new func() // throw error
從控制臺中可以看出,箭頭函數不能當做構造函數,所以不能與new
一起執行。
bind 是指 Function.prototype.bind() 詳細地址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
易錯點
function func() { console.log(this) } func.bind(1).bind(2)() // 1
func = () => { // 這里 this 指向取決于外層 this,參考口訣 7 「不在函數里」 console.log(this) } func.bind(1)() // Window,口訣 1 優先
易錯點
function func() { console.log(this, this.__proto__ === func.prototype) } boundFunc = func.bind(1) new boundFunc() // Object true,口訣 2 優先
apply()
和 call()
的第一個參數都是this
,區別在于通過apply
調用時實參是放到數組中的,而通過call
調用時實參是逗號分隔的。
易錯點
func = () => { // 這里 this 指向取決于外層 this,參考口訣 7 「不在函數里」 console.log(this) } func.apply(1) // Window,口訣 1 優先
易錯點
function func() { console.log(this) } boundFunc = func.bind(1) boundFunc.apply(2) // 1,口訣 3 優先
function func() { console.log(this.x) } obj = { x: 1 } obj.func = func obj.func() // 1
這里就不用代碼例證箭頭函數和 bind 函數的優先級更高了,有興趣可自行嘗試吧。
在函數不滿足前面的場景,被直接調用時,this
將指向全局對象。在瀏覽器環境中全局對象是Window
,在Node.js
環境中是Global
。
先來個簡單的例子。
function func() { console.log(this) } func() // Window
來一個復雜的例子,外層的outerFunc
就起個迷惑目的。
function outerFunc() { console.log(this) // { x: 1 } function func() { console.log(this) // Window } func() } outerFunc.bind({ x: 1 })()
不在函數中的場景,可分為瀏覽器的<script />
標簽里,或Node.js
的模塊文件里。
1、在<script />
標簽里,this
指向Window
。
2、在Node.js
的模塊文件里,this
指向Module
的默認導出對象,也就是module.exports
。
嚴格模式是在ES5
提出的。在ES5
規范之前,也就是非嚴格模式下,this
不能是undefined
或null
。所以**在非嚴格模式下,通過上面七步口訣,如果得出this
指向是undefined
或null
,那么this
會指向全局對象。**在瀏覽器環境中全局對象是Window
,在Node.js
環境中是Global
。
例如下面的代碼,在非嚴格模式下,this
都指向全局對象。
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()
非嚴格模式下執行結果為:
在嚴格模式下,執行同樣的代碼進行對比。記住要一次性將所有代碼復制粘貼到控制臺中,才能運行在嚴格模式下(因為第一行 "use strict
" 才會對后面的代碼生效)。
"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()
嚴格模式下執行結果為:
七步口訣在嚴格模式下和非嚴格模式下都是完備的,只是在非嚴格模式下null
或undefined
會被轉換為全局對象。所以我沒有將這點列入口訣中。
先背誦口訣再做題,“箭頭函數、new
、bind
、apply
和call
、歐比屆點(obj.
)、直接調用、不在函數里”。
1. 下面代碼執行后,func.count 值為多少?
function func(num) { this.count++ } func.count = 0 func(1)
答案
func.count
值為 0。
按照口訣,func()
調用時屬于第 6 類「直接調用」。在非嚴格模式下,this
指向全局對象。this
跟func
一點關系都沒有,所以 func.count
保持不變so easy
。
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
是不是很簡單,你學廢了嗎?
以上就是如何解決js中this指向問題,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。