一文弄懂 this 的前世此生

JavaScript 的 this關鍵字你們都不陌生,根據 this所在的不一樣的運行環境,會產生一些容易讓人困惑的表現和差別,在沒有仔細瞭解 this以前,我對它的理解很是的生硬和片面,但願你們閱讀完這篇內容可以清楚的明白 this的用途。

this 的由來

讓咱們看一下這個栗子:javascript

var name = 'MyWindow'

function SayHi() {
  console.log('Hi, My name is ' + name + '.')
}

var MyJavaScript = {
  name: 'MyJavaScript',
  sayHi: SayHi,
}

SayHi() // Hi, My name is MyWindow.
MyJavaScript.sayHi() // Hi, My name is MyWindow.

能夠看到,當咱們想試圖輸出Hi, My name is MyJavaScript.的時候,仍是輸出了window。由於SayHi函數裏輸出的name變量值一定是沿着當前執行環境的做用域鏈查找的,而SayHi函數被調用時會建立出一個本身的執行環境,按照做用域嵌套順序,SayHi被嵌套在全局執行環境中,在函數內部查找name變量則會找到外層的全局做用域中的name變量,因此不論如何調用都會輸出windowjava

腦袋疼.jpg

那想想,當咱們調用MyJavaScript.sayHi()時要如何準確輸出MyJavaScript對象的name屬性呢?數組

time

噔噔蹬蹬,this機制就此誕生了!!(自帶 bgm)瀏覽器

this被用來指向 函數真正的運行環境

讓咱們改寫一下SayHi方法:app

var name = 'MyWindow'

function SayHi() {
  // 此處發生變化
  console.log('Hi, My name is ' + this.name + '.')
}

var MyJavaScript = {
  name: 'MyJavaScript',
  sayHi: SayHi,
}

SayHi() // Hi, My name is MyWindow.
MyJavaScript.sayHi() // Hi, My name is MyJavaScript.

如上圖,當咱們將name修改成this.name後,sayHi函數當在做爲MyJavaScript對象的某一屬性被調用時,準確的輸出了當前函數的調用者MyJavaScript對象的name屬性值。函數

機靈鬼

由此咱們能夠得知,this對象的做用就是當函數在不一樣的執行環境下被調用,讓咱們可以獲得真正調用函數的對象。與函數定義在哪裏或者函數做用域無關,只關心函數的調用方式。this

========================= 僞裝華麗的分割線 ===========================spa

以上就是this對象的前世,下面會整理一些與this對象相關的必懂知識點,供你們查閱。3d

一些必懂的知識點

this 是什麼

thisJavaScript關鍵字,在非嚴格模式下,它老是指向一個對象,而具體指向哪一個對象是根據函數運行時所在的執行環境動態綁定的。code

爲何須要 this

由於函數能夠在不一樣的運行環境中執行,自身調用或做爲方法調用,爲了獲得當前函數真正運行時的所在執行環境,即函數執行時真正的調用對象this機制就此誕生了。

this 有什麼做用

(同上)指向函數真正的調用對象

this 的指向

劃重點

簡單調用

全局環境下this默認指向全局對象,嚴格模式下則爲undefined,瀏覽器中則爲window對象。

e.g. func() => this默認指向全局對象 => window(瀏覽器下)。

簡單調用

做爲對象的方法調用

this指向由調用方式決定,在函數執行時肯定。

e.g. obj.func() => this指向具體調用對象 => obj

做爲對象的方法調用

這裏能夠理解爲obj.f1()咱們是經過該對象obj找到f1函數的,則它運行時所在環境就是obj環境,this指向obj

做爲構造函數

當一個函數用做構造函數時(使用 new 關鍵字),它的this被綁定到正在構造的新對象。

this指向取決於函數返回的對象(默認無初始化值 => undefined),在類上下文中則是取決於類的構造函數返回對象(默認返回類中定義的全部屬性和方法,不包括靜態方法)。

函數上下文默認 this

無初始化值

函數上下文默認 this

手動添加 this 屬性

手動添加 this 屬性

函數上下文手動返回

函數上下文手動返回

類上下文默認 this

類上下文默認 this

類上下文構造函數手動返回

類上下文構造函數手動返回

是否是想返回了??快結束了啊,再堅持一下 👋

堅持一下

箭頭函數

咱們知道普通函數的this指向在函數執行時肯定,由函數的調用方式決定。

而在 ES6 的箭頭函數中,this指向在函數定義時就肯定了,永遠指向該函數聲明時所在的環境對象,任何其餘方式都沒法修改this的指向。

箭頭函數

靜態方法

由於this對象表明調用這個函數的對象,而靜態方法是屬於類的而不是調用對象,靜態方法成功加載後,調用對象可能還不存在。所以在靜態方法中是找不到this對象的值的。

靜態方法

匿名函數

匿名函數中this的指向也是依舊由函數調用方式決定。

做爲對象的方法

foo做爲objA的方法被調用,this指向objA

簡單調用

foo被指向objA.foo所指向的匿名函數,當foo被簡單調用時,this就指向了全局對象。

setTimeout 和 setInterval

當使用setTimeoutsetInterval時,回調函數中的this默認指向window對象,由於setTimeoutsetIntervalwindow對象提供的方法。

setTimeout

可見,setTimeout中輸出的是window對象上的count屬性。

真的真的第 99 步了,堅持到底啊 👋

再堅持一下

改變 this 指向的幾種方法和區別

call

call

apply

bind

call 和 apply 的區別

call的參數是直接放進去的,第二第三第 n 個參數全都用逗號分隔。

call參數

apply的第二個參數接收的是一個數組,對應傳遞給被綁定的函數。

apply參數

bind

bind用法和call一致,可是bind返回的是被綁定的函數,須要作一次額外的手動調用。

bind

ending

到此本文就結束啦,能堅持看完的小夥伴們必成大才!感謝閱讀,歡迎點贊 🇨🇳
ending

相關文章
相關標籤/搜索