[JavaScript] JavaScript中的作用域和this

前幾天學(xué)習(xí)Standard ML時(shí)候派敷,我接觸了一個(gè)詞語,叫做“詞法作用域”,也叫“靜態(tài)作用域”。然后我發(fā)現(xiàn)了js中的一堆神奇的概念挤悉,貌似突然清晰了(明明之前我也看過的這個(gè)詞的)桶唐。

動態(tài)作用域

動態(tài)作用域現(xiàn)在不太采用缰儿,但是原理特別簡單元镀。整個(gè)程序只有一個(gè)作用域的棧,每次在定義新的綁定時(shí)候掌测,都直接push進(jìn)去内贮,每次退出函數(shù)的時(shí)候,或者退出大括號包圍的環(huán)境時(shí)候汞斧,把綁定push出來夜郁。早期的語言可能會用它。每次需要某個(gè)值時(shí)候粘勒,不斷從棧頂往下面找值竞端,直到找到某個(gè)標(biāo)識符符合的映射。

詞法作用域

現(xiàn)在大部分的語言都是采用詞法作用域了仲义。普通老百姓(排除學(xué)術(shù)派的小伙伴)用的語言都是婶熬。

無頭等函數(shù)的語言的詞法作用域

在沒有first-class function的語言,比如C中埃撵,在編譯時(shí)期就確定了每個(gè)名字對應(yīng)的作用域赵颅。并不會因?yàn)檫\(yùn)行環(huán)境的不一樣取到不一樣的值,也不會因?yàn)檎{(diào)用的順序不同而有時(shí)候存在暂刘,有時(shí)候消失饺谬。

頭等函數(shù)的語言的詞法作用域

在first-class function的語言中,比如js中谣拣。(我們只考慮不采用eval和with的js)
函數(shù)的內(nèi)部綁定可能會隨著傳出或者傳入函數(shù)對象募寨,同時(shí)把綁定也傳過去。

比如

const f = a=>b=>a+b
const m = f(1)

m無論在什么環(huán)境下森缠,都能充當(dāng)+1的函數(shù)拔鹰。因?yàn)閮?nèi)部有a=1的綁定。
(所以贵涵,js的垃圾回收可能會有點(diǎn)復(fù)雜)

JavaScript的函數(shù)調(diào)用

我把JavaScript的函數(shù)調(diào)用分為下面幾種情況討論

最簡單的call調(diào)用

最簡單的情況是call列肢,是毫無黑魔法的情況恰画。

函數(shù)定義時(shí)候,都會隱含著一個(gè)默認(rèn)參數(shù)瓷马,this拴还。

MDN上,寫著call的語法欧聘。

fun.call(thisArg, arg1, arg2, ...)

我們可以忽略環(huán)境地片林,顯式指定函數(shù)的this參數(shù)。

比如

const bar={
  foo:function (){
    console.log(this);
  }  
}
bar.foo.call("2333")
bar.foo.call(Object("2333"))
bar.foo.call(undefined)
bar.foo.call(null)
bar.foo()
const foo = bar.foo
foo()

由于怀骤,this一定要是Object费封,是其他類型的話,會被轉(zhuǎn)成Object的晒喷,所以前兩次調(diào)用是一樣的效果孝偎;
第三,四次由于在非嚴(yán)格模式下凉敲,會自動指向全局的global或者window;

等價(jià)于call的apply調(diào)用

apply只是把call的后續(xù)n個(gè)參數(shù)放在一個(gè)數(shù)組里了寺旺。不細(xì)述爷抓。

最常見的隱含this調(diào)用

const bar={
  foo:function (){
    console.log(this);
  }  
}
bar.foo.call("2333")
bar.foo.call(Object("2333"))
bar.foo.call(undefined)
bar.foo.call(null)
bar.foo()
const foo = bar.foo
foo()

第五次時(shí)候,不采用call調(diào)用阻塑,則會把調(diào)用的環(huán)境bar傳進(jìn)去蓝撇;
第六次時(shí)候,不采用call調(diào)用陈莽,則會把調(diào)用的環(huán)境window傳進(jìn)去渤昌。

默認(rèn)傳入的this參數(shù)的n種情況

  • 當(dāng)以對象里的方法的方式調(diào)用函數(shù)時(shí),它們的 this 是調(diào)用該函數(shù)的對象.
  • 在箭頭函數(shù)中走搁,this 是根據(jù)當(dāng)前的詞法作用域來決定的独柑,就是說,箭頭函數(shù)會繼承外層函數(shù)調(diào)用的this 綁定(無論this 綁定到什么)私植。在全局作用域中忌栅,它會綁定到全局對象上。
  • 使用new關(guān)鍵字曲稼,它的this被綁定到正在構(gòu)造的新對象索绪。
  • 該方法存在于一個(gè)對象的原型鏈上,那么this指向的是調(diào)用這個(gè)方法的對象贫悄,就好像該方法本來就存在于這個(gè)對象上
  • 用作getter或setter的函數(shù)都會把 this 綁定到正在設(shè)置或獲取屬性的對象瑞驱。
  • 當(dāng)函數(shù)被用作事件處理函數(shù)時(shí),它的this指向觸發(fā)事件的元素(一些瀏覽器在使用非addEventListener的函數(shù)動態(tài)添加監(jiān)聽函數(shù)時(shí)不遵守這個(gè)約定)窄坦。
  • 當(dāng)代碼被內(nèi)聯(lián)處理函數(shù)調(diào)用時(shí)唤反,它的this指向監(jiān)聽器所在的DOM元素

(以上都是MDN上摘錄的晰筛,習(xí)慣了js的人應(yīng)該一看都可以想到應(yīng)用場景(吐槽:this真是一個(gè)奇葩的設(shè)計(jì),好好的和python一個(gè)搞一個(gè)顯示的self參數(shù)不是更棒拴袭?))

一個(gè)永遠(yuǎn)劫持this參數(shù)的函數(shù)的bind方法

bind可能會改變this的指向读第,這個(gè)有一點(diǎn)點(diǎn)復(fù)雜,我寫了個(gè)函數(shù)模擬拥刻,我覺得我應(yīng)該新開一篇文章講解(雖然好多人曾經(jīng)都講過了)

總結(jié)

js采用的是一直都是詞法作用域怜瞒。

this是一個(gè)隱式傳遞的參數(shù),由多條復(fù)雜規(guī)矩限定般哼。

如果我們不使用call吴汪,apply和bind,js的this的由于默認(rèn)傳入的this的特殊行為蒸眠,表現(xiàn)的行為類似于動態(tài)作用域漾橙,實(shí)質(zhì)還是詞法作用域。(這個(gè)是何幻大大教我的)

我是在理解無黑魔法的基礎(chǔ)上的call楞卡,把其他等價(jià)過去理解的霜运。另外我建議不要使用arguments,因?yàn)閑s6給了更好的解決方案蒋腮。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末淘捡,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子池摧,更是在濱河造成了極大的恐慌焦除,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件作彤,死亡現(xiàn)場離奇詭異膘魄,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)竭讳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門创葡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人代咸,你說我怎么就攤上這事蹈丸。” “怎么了呐芥?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵逻杖,是天一觀的道長。 經(jīng)常有香客問我思瘟,道長荸百,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任滨攻,我火速辦了婚禮够话,結(jié)果婚禮上蓝翰,老公的妹妹穿的比我還像新娘。我一直安慰自己女嘲,他們只是感情好畜份,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著欣尼,像睡著了一般爆雹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上愕鼓,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天钙态,我揣著相機(jī)與錄音,去河邊找鬼菇晃。 笑死册倒,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的磺送。 我是一名探鬼主播驻子,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼册着!你這毒婦竟也來了拴孤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤甲捏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后鞭执,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體司顿,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年兄纺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了大溜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,724評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡估脆,死狀恐怖钦奋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情疙赠,我是刑警寧澤付材,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站圃阳,受9級特大地震影響厌衔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜捍岳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一富寿、第九天 我趴在偏房一處隱蔽的房頂上張望睬隶。 院中可真熱鬧,春花似錦页徐、人聲如沸苏潜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽恤左。三九已至,卻和暖如春贰锁,著一層夾襖步出監(jiān)牢的瞬間赃梧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工豌熄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留授嘀,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓锣险,卻偏偏與公主長得像蹄皱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子芯肤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容