普通函數(shù)的this指向 簡單說說
首先,按照慣例,我們先舉個栗子:
var bar = 2; function foo() { this.bar = 1; this.getBar = function() { console.log(this.bar); } } var test = new foo(); var getBar = test.getBar; test.getBar(); //1 getBar(); //2
通過這個例子我們就能看到,雖然是同一個函數(shù),但是實際上得到的結(jié)果卻不一樣。這個原因相信大家都能知道。不知道的也告訴你:this其實是指向調(diào)用該函數(shù)的那個對象。那么當(dāng)我們在全局環(huán)境中調(diào)用的時候,this自然就指向了全局環(huán)境。
那么到是有個問題:this為什么會隨調(diào)用者變化而變化?
這可能需要你繼續(xù)往下看看
深入說說那么如果說深層次的理解this的指向,我覺得大概可以從數(shù)據(jù)類型講起
我們都知道,棧中存放的是基本數(shù)據(jù)類型,也就是String、Number、Boolean、Symbol、Null、Undefined這七種數(shù)據(jù)類型,當(dāng)然Symbol是ES6新增的一個數(shù)據(jù)類型。那么堆中存放的就是一些引用類型了,如Obejct、Function。實際上當(dāng)我們定義一個引用類型的時候,js會同時定義一個地址指針指向內(nèi)存中的對象。
例如:當(dāng)我們聲明一個字面量對象時候let a = {num:1};實際上a中存放的是指向{num:1}的地址
現(xiàn)在我們解析一下上面那段代碼是如何執(zhí)行的
// 在全局環(huán)境下定義一個變量bar var bar = 2; function foo() { //在foo中也聲明了一個bar this.bar = 1; //在foo中聲明一個getBar函數(shù) this.getBar = function() { console.log(this.bar); } } //構(gòu)造函數(shù)模式自定義對象,將foo的this賦予test var test = new foo(); //將test中的getBar方法賦予getBar var getBar = test.getBar; //調(diào)用test中的getBar test.getBar(); //1 //調(diào)用getBar getBar(); //2
現(xiàn)在列出來一看,放佛恍然大悟,終于知道為啥輸出的是不同的結(jié)果了。那么我這里倒是有幾個問題
為什么調(diào)用同一個函數(shù)卻有不同的結(jié)果?
foo中的this是指向foo的,為什么foo中的函數(shù)可以取得外部的this?
為什么this會隨調(diào)用它的對象變化而變化?
ok,其實要弄清楚上述問題,我們需要明白一點,函數(shù)也是個引用類型。那么我們上面講過,創(chuàng)建引用類型的時候會同時創(chuàng)建一個地址指針。那么我們就可以這樣理解上面的foo對象
實際上foo中的getBar只是存放了一個函數(shù)的地址而已*。那么這個函數(shù)并不是foo所私有。什么東西是foo的呢?一個值為1的bar和一個指向function() {console.log(this.bar);}函數(shù)的getBar而已。
這樣我們就不難理解,為什么調(diào)用同一個函數(shù)會有不一樣的結(jié)果了,因為這個函數(shù)并不是foo所私有。好比內(nèi)存就是深圳,函數(shù)就只是深圳的一套房。getBar就是這套房的鑰匙。那么一開始foo這個人建好了這房子,就他有這房子的鑰匙,那么當(dāng)然只有他能進出該房子,后來有一天他把鑰匙多配了一把給了window這好朋友。于是乎window也能進這套房了。給window配鑰匙的過程:var getBar = test.getBar;這里只是將該函數(shù)的地址賦給全局下的getBar而已,房子也只是一套房子,函數(shù)還是一個函數(shù)。
由于函數(shù)可以在不同的運行環(huán)境執(zhí)行,所以需要有一種機制,能夠在函數(shù)體內(nèi)部獲得當(dāng)前的運行環(huán)境(context)。所以,this就出現(xiàn)了,它的設(shè)計目的就是在函數(shù)體內(nèi)部,指代函數(shù)當(dāng)前的運行環(huán)境。
所以當(dāng)window調(diào)用這個函數(shù)的時候,this就不是指向foo了。而是指向window。this是指向他們自己。window的衣服不會在進了foo的房子以后就變成foo的衣服。
ok,我們現(xiàn)在再把剛剛的代碼重新注釋一下
// 在全局環(huán)境下定義一個變量bar var bar = 2; function foo() { //在foo中也聲明了一個bar this.bar = 1; //在foo中聲明一個getBar函數(shù),getBar存放該函數(shù)的地址 this.getBar = function() { console.log(this.bar); } } //構(gòu)造函數(shù)模式自定義對象,將foo的this賦予test var test = new foo(); //將test中的getBar方法的地址賦予全局的getBar var getBar = test.getBar; //調(diào)用test中的getBar函數(shù) test.getBar(); //1 //調(diào)用getBar函數(shù) getBar(); //2
于是乎我們就把普通的this指向弄明白了。順便還明白了堆棧的區(qū)別。接下來看看不普通的函數(shù)this指向是如何的
箭頭函數(shù)this指向箭頭函數(shù)內(nèi)沒有this,箭頭函數(shù)的this是父級函數(shù)的this
// 在全局環(huán)境下定義一個變量bar var bar = 2; function foo() { //在foo中也聲明了一個bar this.bar = 1; //在foo中定義一個箭頭函數(shù),getBar存放該函數(shù)的地址 this.getBar = () => { console.log(this.bar); } } //構(gòu)造函數(shù)模式自定義對象,將foo的this賦予test var test = new foo(); //將test中的getBar方法的地址賦予全局的getBar var getBar = test.getBar; //調(diào)用test中的getBar函數(shù) test.getBar(); //1 //調(diào)用getBar函數(shù) getBar(); //1
如果定義了箭頭函數(shù)的情況下,this執(zhí)行就不會隨意的改變了。普通函數(shù)的this是會跟隨調(diào)用者變化,但是箭頭函數(shù)就很特別,他只會繼承父級的this,而且一旦建立就不會改變了。所以在這里我們就可以看見,盡管全局下面調(diào)用getBar,但是實際上還是取到了foo的this。
因此箭頭函數(shù)不可以用來當(dāng)作構(gòu)造函數(shù)。因為它本身是沒有this的!
所以箭頭函數(shù)使用的話需要與普通函數(shù)區(qū)別開這點,它的this指向定義函數(shù)時候的父級。
后話關(guān)于this就介紹到這里,如果有什么不懂的歡迎隨時提問,我會隨時回答大家的問題。
那么最后,成功不在一朝一夕,我們都需要努力
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/96390.html
摘要:深入認(rèn)知前言關(guān)于,平時我們僅僅做到了使用,但是真的理解為什么這么使用嗎這里詳細(xì)介紹一些我們常用的語法。在以下,是沒有塊級作用域的,只有函數(shù)作用域。而如果在作用域中嵌套作用域,那么就會有作用域鏈。 本文當(dāng)時寫在本地,發(fā)現(xiàn)換電腦很不是方便,在這里記錄下。 深入認(rèn)知 Javascript 前言 關(guān)于 Javascript,平時我們僅僅做到了使用,但是真的理解為什么這么使用嗎? 這里詳細(xì)...
摘要:箭頭函數(shù)的尋值行為與普通變量相同,在作用域中逐級尋找。題目這次通過構(gòu)造函數(shù)來創(chuàng)建一個對象,并執(zhí)行相同的個方法。 我們知道this綁定規(guī)則一共有5種情況: 1、默認(rèn)綁定(嚴(yán)格/非嚴(yán)格模式) 2、隱式綁定 3、顯式綁定 4、new綁定 5、箭頭函數(shù)綁定 其實大部分情況下可以用一句話來概括,this總是指向調(diào)用該函數(shù)的對象。 但是對于箭頭函數(shù)并不是這樣,是根據(jù)外層(函數(shù)或者全局)作用域(...
摘要:執(zhí)行上下文和執(zhí)行棧是中關(guān)鍵概念之一,是難點之一。理解執(zhí)行上下文和執(zhí)行棧同樣有助于理解其他的概念如提升機制作用域和閉包等。函數(shù)執(zhí)行完成,函數(shù)的執(zhí)行上下文出棧,并且被銷毀。 前言 如果你是一名 JavaScript 開發(fā)者,或者想要成為一名 JavaScript 開發(fā)者,那么你必須知道 JavaScript 程序內(nèi)部的執(zhí)行機制。執(zhí)行上下文和執(zhí)行棧是JavaScript中關(guān)鍵概念之一,是Ja...
摘要:執(zhí)行上下文和執(zhí)行棧是中關(guān)鍵概念之一,是難點之一。理解執(zhí)行上下文和執(zhí)行棧同樣有助于理解其他的概念如提升機制作用域和閉包等。函數(shù)執(zhí)行完成,函數(shù)的執(zhí)行上下文出棧,并且被銷毀。 前言 如果你是一名 JavaScript 開發(fā)者,或者想要成為一名 JavaScript 開發(fā)者,那么你必須知道 JavaScript 程序內(nèi)部的執(zhí)行機制。執(zhí)行上下文和執(zhí)行棧是JavaScript中關(guān)鍵概念之一,是Ja...
摘要:本期推薦文章類內(nèi)存泄漏及如何避免,由于微信不能訪問外鏈,點擊閱讀原文就可以啦。四種常見的內(nèi)存泄漏劃重點這是個考點意外的全局變量未定義的變量會在全局對象創(chuàng)建一個新變量,如下。因為老版本的是無法檢測節(jié)點與代碼之間的循環(huán)引用,會導(dǎo)致內(nèi)存泄漏。 (關(guān)注福利,關(guān)注本公眾號回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導(dǎo)) 本周正式開始前端進階的第一期,本周的主題...
閱讀 3765·2021-11-22 13:52
閱讀 3633·2019-12-27 12:20
閱讀 2402·2019-08-30 15:55
閱讀 2156·2019-08-30 15:44
閱讀 2274·2019-08-30 13:16
閱讀 589·2019-08-28 18:19
閱讀 1903·2019-08-26 11:58
閱讀 3450·2019-08-26 11:47