Javascript是一門基於對象的動態語言,也就是說,全部東西都是對象,一個很典型的例子就是函數也被視爲普通的對象。前端
其中this就是實現面向對象的一個很是重要的特性,可是 this在Javascript很是容易理解錯,尤爲是對於接觸靜態語言比較久的同窗來講。並且 this又是面試中和實際項目中的重中之重,不得不單獨拿出一篇文章來把它理解透透的。面試
上面說到this參數是面向對象Javascript編程的一個重要組成部分,表明函數調用相關聯的對象,也稱爲函數上下文。我知道,你多是個初學 JS 的同窗,聽不懂,不要緊,不用擔憂,由於下面還有動畫來更好的理解。算法
什麼是 this呢?上邊咱們說 this是一個對象,是個啥對象?我們就來動手敲代碼打印一下。咱們最多見的 this是在一個函數中, JS 的函數調用有兩種方式,一種是咱們直接調用,另一種就是經過 new 的方式來調用,咱們經過兩種方式來打印一下 this值是否相同?。編程
控制檯輸出以下:數組
吆喝?咦?雖然都是在函數中,咋打印出來的不同呢?直接經過函數調用的方式打印出來的 this指向的是全局變量Window;經過new的方式調用的函數當作爲構造函數,爲了可以建立一個實例對對象,它的 this值指向生成的實例對象。網絡
那咱們經過上邊的一頓亂操做,知道了 this是一個對象,可是咱們不一樣的操做 this指向的對象是不相同的。寫到這裏,知道 this是個什麼東西就能夠了,下面咱們再慢慢深刻 this原理。數據結構
既然咱們知道 this 是什麼東西了,可是怎麼判斷 this的值呢?也是咱們上邊沒有解決的問題。this的指向有三種狀況,只要理解了這三種狀況,也不用死記硬背,判斷 this如魚得水,在面試中給面試官講的倒背如流。app
三種 this指向狀況:函數
一、對象調用,this 指向該對象(前邊誰調用 this 就指向誰)。 學習
對於第一種狀況,經過對象調用的方式,this指向誰?要想一探究竟,必須動手實踐一下。小鹿,上代碼,好嘞~。
控制檯打印:
咱們經過親手測試,咱們發現 this的指向就是 obj,因此咱們總結概括爲誰調用了函數, this就指向誰,很簡單吧,咱們繼續向下看。
二、直接調用的函數,this 指向的是全局 window 對象。
其實這也屬於第一種狀況,若是咱們直接在全局函數調用了函數,實際上是全局的對象 Window調用了函數,根據第一條咱們得出的結論,誰調用的函數,this就指向誰,想必你已經知道了第二種狀況 this指向的就是 Window。
三、經過 new 的方式,this 永遠被綁定在新建立的對象上,任何方式都改變不了 this 的指向。
第三種方式剛纔咱們也測試過了,this指向的是指向生成的對象實例,不少好奇的小夥伴就會問小鹿,很好奇 new的內部實現,到底作了什麼,其實沒什麼複雜的,不告訴你估計你也經過上邊的兩個結論能夠得出。
咱們從的到的結果進行反推,經過 new的方式 this 指向的是生成的對象實例,那咱們猜想確定內部讓這個實例對象調用了函數,因此 this 才指向生成的對象實例。
真實的狀況是這樣子嗎?確實是,咱們 new的過程,其實在內部建立了一個空對象,而後將構造函數傳入的參數和屬性掛在了這個空對象上,而後返回了這個對象。還涉及該空對象到原型鏈的的掛載,想要具體瞭解,能夠本身探究下,這裏很少說了。
擴展:箭頭函數的 this 指向誰?
咱們都知道 ES6 以後,爲了使用函數更加方便,在項目中咱們會使用箭頭函數,書寫方式:
運行程序,控制檯輸出:
咱們能夠得出結論,this在箭頭函數中失效了,由於這是因爲箭頭函數沒有單獨的 this值。箭頭函數的 this與聲明所在的上下文相同。也就是說調用箭頭函數的時候,不會隱士的調用 this參數,而是從定義時的函數繼承上下文。
有關箭頭函數這一點,必定要注意,面試的時候也會常常給你刨坑哦!
咱們對 this的指向已經把它翻了個底朝天,可是不要傲嬌,須要本身找點有關 this 的大廠面試題去作,這樣鞏固一下加深理解。
this能夠指向不一樣的對象,咱們想要改變 this有沒有辦法呢?有的,改變 this的方法共有三種,咱們具體看看這三種方法之間的實現和區別,也是面試重點哦!
一、call 方法
call方法用來改變 this的指向,具體我們先看實例:
控制檯輸出以下:
二、apply 方法
咱們再來看apply方法,一樣舉個例子:
咱們發現輸出的值相同,咱們先不比較二者的區別是什麼,咱們繼續往下看bind函數。
三、bind 方法
咱們在用 bind函數舉個例子:
控制檯輸出以下:
四、call、apply、bind 三者的區別是什麼?
咱們對於三者都進行舉例運行了,咱們開始作總結概括,咱們先找找三者的共同點是什麼?
一、都能改變 this 指向,第一個傳遞的參數都是 this 指向的對象。
二、三者都採用的後續傳參的形式。
三者相同點表面上都能看出來,功能都是同樣的,可是對於不一樣點,就涉及到細節了,不知道你發現了沒有?
一、call的傳參是單個傳遞的,而 apply後續傳遞的參數是數組形式,而 bind沒有規定,傳遞值和數組均可以。
二、call和 apply函數的執行是直接執行的,而 bind函數會返回一個函數,而後咱們想要調用的時候纔會執行。
你可能會有疑惑,小鹿,難道你就是這樣表面看出的嗎?雖然咱們表面能夠看得出,那不妨咱們本身手寫一個 call、apply、和 bind的吧,看了源碼的實現,你會以爲這三個函數也沒有什麼難的。由於涉及到時間問題,咱們就不展開講了,小鹿把代碼貼到下邊了,感興趣的能夠研究一下。
一、手寫 call 函數
三、手寫 bind 函數
PS:若是咱們使用上邊的方法改變箭頭函數的 this 指針,會發生什麼狀況呢?可否對齊進行改變呢?
因爲箭頭函數沒有本身的this指針,經過 call() 或 apply() 方法調用一個函數時,只能傳遞參數(不能綁定this),他們的第一個參數會被忽略。
今天咱們認識了 JS 中 this的使用,想必不管你是初學者仍是已經接觸過 JS 的小夥伴,這篇文章應該基本能夠看明白,文章可能寫的比較 low,小鹿的能力就這麼大了,還須要後續和大佬好好學習,爭取寫出更高難度和質量的文章分享給你們。
最後,每次文章寫做加上做圖須要好幾個小時,原創真心不容易,點個贊、發個Blink,感謝各位小夥伴們的支持!
文章+動畫寫了好幾個小時,不妨點贊支持一下。嘻嘻,你不點贊說明你很自私,你怕那麼好的文章讓別人也看到。開個小小玩笑。
能夠關注小鹿公衆號:「小鹿動畫學編程」,後臺回覆:「資源」。送你一份小鹿以前自學的資料和拉你進免費學習羣哦!
做者Info:
【做者】:小鹿
【原創公衆號】:小鹿動畫學編程。
【簡介】:和小鹿同窗一塊兒用動畫的方式從零基礎學編程,將 Web前端領域、數據結構與算法、網絡原理等通俗易懂的呈獻給小夥伴。先定個小目標,原創 1000 篇的動畫技術文章,和各位小夥伴共同努力一塊兒學習!公衆號回覆 「資料」 送一從零自學資料大禮包!
【轉載說明】:轉載請說明出處,謝謝合做!~