摘要:所以構(gòu)造函數(shù)里的指的就是將要被出來的新對象。希望看完這篇文章之后,再有人問指向的問題,你可以嘴角微微上揚,冷笑一聲不要再問我的指向問題了。
this的指向已經(jīng)是一個老生常談的問題,每逢面試都要去復習復習,近來鞏固js的基礎(chǔ),決心徹底掌握這個知識點,一勞永逸。說明一下,為了不影響大家的思考過程,下面的代碼都不會去注釋答案,想知道答案,只需要去控制臺執(zhí)行一下。
四類場景逐一擊破首先,分析this的指向共有四種類型,在分析之前,我們首先帶好兩個錦囊:
1.函數(shù)被調(diào)用時(即運行時)才會確定該函數(shù)內(nèi)this的指向。因為在函數(shù)中this與arguments是兩個特殊的變量,在函數(shù)被調(diào)用時才會取得它們,而且搜索這兩個變量時只會在活動對象范圍里面去搜。(有關(guān)活動對象與變量對象的知識,請移步到j(luò)s 中的活動對象 與 變量對象 什么區(qū)別?)
2.要確定函數(shù)中this的指向,必須先找到該函數(shù)被調(diào)用的位置。
var a = 1 function test () { console.log(this.a) } test()
直接不帶任何引用形式去調(diào)用函數(shù),則this會指向全局對象,因為沒有其他影響去改變this,this默認就是指向全局對象(瀏覽器是window,Node中是global)的。這個結(jié)論是在非嚴格模式的情況下,嚴格模式下這個this其實是undefined的。
認準第二種“xxx.test()”形式var a = 1 function test () { console.log(this.a) } var obj = { a: 2, test } obj.test()
這種形式對比起第一種,很明顯test()已經(jīng)是名花有主的了!看清楚,是誰呼喚的test()?沒錯,就是obj,所以this的指向就不言而喻了。一句話,誰去調(diào)用這個函數(shù)的,這個函數(shù)中的this就綁定到誰身上。
var a = 1 function test () { console.log(this.a) } var obj = { a: 2, test } var obj0 = { a: 3, obj } obj0.obj.test()
即使是這種串串燒的形式,結(jié)果也是一樣的,test()中的this只對直屬上司(直接調(diào)用者obj)負責。再來看一個綜合點的例子:
var a = 1 function test () { console.log(this.a) } var obj = { a: 2, test } var testCopy = obj.test testCopy()
嗯,聰明的你一定想到,換了個名字就能騙到我了!?雖然經(jīng)過了一波改名換姓,但本質(zhì)上還不是obj.test()嘛!結(jié)果一定和上面一樣!唔,請F12在控制臺試試,竟然……其實這里并不需要去思考什么,按照我們的套路,我們就認函數(shù)調(diào)時的樣子,有沒有看到最后調(diào)用的時候跟第一種情況一毛一樣?我再介紹一個場景大家一定不會覺得陌生:
var a = 1 function test () { console.log(this.a) } var obj = { a: 2, test } setTimeout(obj.test)
你可以意淫一下setTimeout的本質(zhì),是不是相當于有一個setTimeout函數(shù),接收兩個參數(shù):
function setTimeout (fn, time) { // 這里干了一大波不可描述的事情,最后會去調(diào)一下你傳進來的回調(diào)函數(shù) fn() }
看到怎樣調(diào)用你傳進來的函數(shù)了嗎!?再想想我們第一種形式的標題認準第一種“test()”形式。
認準第三種“test.call(xxx) / test.apply(xxx) / test.bind()”形式看了上面兩種形式之后,你可能會想,我非常討厭上面那些矯情的扭扭捏捏的九曲十八彎的調(diào)用方式,讓人毫無安全感,我要我自己指定this的指向,我要勝天半子!沒問題,我的代碼我做主:
var a = 1 function test () { console.log(this.a) } var obj = { a: 2, test } var testCopy = obj.test testCopy.call(obj)
可以看到,我們通過call(apply跟call的區(qū)別只是傳參,作用是一樣的,bind有點區(qū)別,bind能讓我們的函數(shù)延遲執(zhí)行,apply與call調(diào)用就執(zhí)行,所以bind這樣的形式我們也稱為函數(shù)柯里化,這些就不是我們這里要說的啦)來調(diào)用testCopy,并且傳入了你想要this指向的上下文,那么this就會乖乖按照你的指示行事啦??吹竭@里,我們也可以想象第一、二種形式其實可以轉(zhuǎn)化成call/apply的形式,有一篇比較棒的文章描述了這樣的思考過程,大家也可以看看this 的值到底是什么?一次說清楚
認準第四種“new test()”形式終于到了最后一種形式了,這種形式比較好認,因為有標志性的new:
var a = 1 function test (a) { this.a = a } var b = new test(2) console.log(b.a)
new這個操作符其實是new了一個新對象出來,而被new的test我們稱為構(gòu)造函數(shù),我們可以在這個構(gòu)造函數(shù)里定義一下將要到來的新對象的一些屬性。那么在構(gòu)造函數(shù)里,我們怎樣去描述這個還未出生的新對象呢?沒錯,就是用this。所以構(gòu)造函數(shù)里的this指的就是將要被new出來的新對象。
One more thing感謝大家看到這里,但還要說最后一種形式。等等,不是說好的只有四種形式嗎!稍安勿躁,正常套路下確實只有上面四種,但是有個東西別忘了,就是大家最喜歡的箭頭函數(shù)。
var a = 1 var test = () => { console.log(this.a) } var obj = { a: 2, test } obj.test()
來,往上翻一下我們的第一個錦囊,“函數(shù)被調(diào)用時(即運行時)才會確定該函數(shù)內(nèi)this的指向。”現(xiàn)在函數(shù)這兩個字要加個詞修飾一下,變成普通函數(shù)(非箭頭函數(shù))才能區(qū)別于箭頭函數(shù)。箭頭函數(shù)中的this在函數(shù)定義的時候就已經(jīng)確定,它this指向的是它的外層作用域this的指向。
最后我們最后還要說:“到此為止,真的沒有了?!?br>希望看完這篇文章之后,再有人問this指向的問題,你可以嘴角微微上揚,冷笑一聲:“不要再問我this的指向問題了?!?br>揚長而去。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/95849.html
摘要:不要再問我的問題系列一不要再問我的指向問題了二不要再問我跨域的問題了移動端適配的問題,一般來說我們都不會去深究,因為這種東西都是配置一次就再也不用管的了,接到設(shè)計圖就按照祖?zhèn)魈茁窋]就完事了。 不要再問我XX的問題系列:一、不要再問我this的指向問題了二、不要再問我跨域的問題了 移動端適配的問題,一般來說我們都不會去深究,因為這種東西都是配置一次就再也不用管的了,接到設(shè)計圖就按照祖?zhèn)?..
摘要:不要再問我的問題系列一不要再問我的指向問題了二不要再問我跨域的問題了移動端適配的問題,一般來說我們都不會去深究,因為這種東西都是配置一次就再也不用管的了,接到設(shè)計圖就按照祖?zhèn)魈茁窋]就完事了。 不要再問我XX的問題系列:一、不要再問我this的指向問題了二、不要再問我跨域的問題了 移動端適配的問題,一般來說我們都不會去深究,因為這種東西都是配置一次就再也不用管的了,接到設(shè)計圖就按照祖?zhèn)?..
摘要:不要再問我的問題系列一不要再問我的指向問題了二不要再問我跨域的問題了移動端適配的問題,一般來說我們都不會去深究,因為這種東西都是配置一次就再也不用管的了,接到設(shè)計圖就按照祖?zhèn)魈茁窋]就完事了。 不要再問我XX的問題系列:一、不要再問我this的指向問題了二、不要再問我跨域的問題了 移動端適配的問題,一般來說我們都不會去深究,因為這種東西都是配置一次就再也不用管的了,接到設(shè)計圖就按照祖?zhèn)?..
摘要:不過大多數(shù)講解還停留在對功能使用的層面,其底層的很多原理,很多人可能并不知曉。每個線程池里的線程就僅僅用于請求那個服務(wù)。 歡迎關(guān)注微信公眾號:石杉的架構(gòu)筆記(id:shishan100) 每日更新!精品技術(shù)文章準時送上! 目錄 一、業(yè)務(wù)場景介紹 二、Spring Cloud核心組件:Eureka 三、Spring Cloud核心組件:Feign 四、Spring Cloud核心組件:R...
摘要:不過大多數(shù)講解還停留在對功能使用的層面,其底層的很多原理,很多人可能并不知曉。每個線程池里的線程就僅僅用于請求那個服務(wù)。 歡迎關(guān)注微信公眾號:石杉的架構(gòu)筆記(id:shishan100) 每日更新!精品技術(shù)文章準時送上! 目錄 一、業(yè)務(wù)場景介紹 二、Spring Cloud核心組件:Eureka 三、Spring Cloud核心組件:Feign 四、Spring Cloud核心組件:R...
閱讀 3574·2021-11-24 09:38
閱讀 3272·2021-11-22 09:34
閱讀 2169·2021-09-22 16:03
閱讀 2464·2019-08-29 18:37
閱讀 444·2019-08-29 16:15
閱讀 1834·2019-08-26 13:56
閱讀 931·2019-08-26 12:21
閱讀 2272·2019-08-26 12:15