探究javascript的運行時

前言

我們天天寫業(yè)務,公司小吟宦,業(yè)務簡單篮洁,經(jīng)驗不值錢,出來面試被說沒亮點殃姓,寫個業(yè)務都要問原理袁波,如果沒答好,就開始以下場景:

面試官:“你有什么要問我的嗎蜗侈?”
你:“額篷牌,我,我沒什么要問的踏幻。枷颊。〗斜叮”

不偷卧,其實你不是這樣子的豺瘤,你不想這么憋屈的離開吆倦,你不想就這樣辛辛苦苦跑過來被兩三句話打發(fā)掉!

所以坐求,開啟絕地反擊模式:

面試官:“你有什么要問我的嗎蚕泽?”
你:“js的運行時是怎么樣的?”
面試官:“我桥嗤。须妻。》毫欤”

運行時解析

如下代碼

var a = 1
let b = 2
const c = {k: 3}

function d () {
  console.log(a)
  var a = 11
  let b = 22
  dd()
}

function dd () {
   console.log(b)
}

d() // 輸出啥荒吏? undefined 2

如果你是js老手, 一看d()執(zhí)行結(jié)果就知道是a變量提升了打印undefined,dd方法執(zhí)行打印2渊鞋,那a為什么會提升呢, 怎么不是打印外面的變量a = 1呢绰更?b怎么不打印22呢?想要弄清楚這些問題锡宋,就要了解js的執(zhí)行機制了儡湾。

js運行時有兩個階段:編譯階段、執(zhí)行階段执俩。
編譯階段:js通過編譯生成執(zhí)行上下文和可執(zhí)行代碼兩部分徐钠。
執(zhí)行階段:執(zhí)行可執(zhí)行代碼,輸出結(jié)果役首。
可以理解如下圖

js運行時

執(zhí)行上下文是啥尝丐?可執(zhí)行代碼又是啥显拜?

執(zhí)行上下文是 JavaScript 執(zhí)行一段代碼時的運行環(huán)境,比如調(diào)用一個函數(shù)爹袁,就會進入這個函數(shù)的執(zhí)行上下文讼油,確定該函數(shù)在執(zhí)行期間用到的諸如 this、變量呢簸、對象以及函數(shù)等矮台。

可執(zhí)行代碼就是指js引擎可以執(zhí)行的代碼,這些代碼可以是【字節(jié)碼根时、機器碼】瘦赫。我們寫的js代碼它看不懂,也不會執(zhí)行蛤迎,它要先把js編譯成字節(jié)碼确虱、機器碼才行。

其實不管是什么高級語言代碼都要編譯才能執(zhí)行替裆,后面再說校辩。

了解了這兩個概念還不夠,執(zhí)行上下文里面有哪些內(nèi)容辆童?可以如下圖表示


執(zhí)行上下文.png

看上圖宜咒,這是編譯階段的輸出,可以了解到一些重要信息:
變量環(huán)境:執(zhí)行上下文中var 聲明的變量把鉴,且賦值默認值undefined故黑。
詞法環(huán)境:執(zhí)行上下文中l(wèi)et const聲明的變量,這是解決變量提升問題庭砍,重點這是在es6加入的场晶,es5并沒有詞法環(huán)境。
outer: 外部引用怠缸,其實在每個執(zhí)行上下文中诗轻,都包含了一個外部引用,用來指向外部的執(zhí)行上下文揭北,我們把這個外部引用稱為 outer扳炬。在js中有全局執(zhí)行上下文、函數(shù)上下文之說罐呼,每個上下文的外部引用都是在編譯時決定的鞠柄,這個和代碼的編譯時的位置有關,也稱為詞法作用域嫉柴。詞法作用域就是指作用域是由代碼中函數(shù)聲明的位置來決定的厌杜,所以詞法作用域是靜態(tài)的作用域,通過它就能夠預測代碼在執(zhí)行過程中如何查找標識符。理解可以參考下圖

詞法作用域夯尽,編譯時根據(jù)位置確定

this: this是一套和作用域無關的獨立機制瞧壮,這個你可以另外找到相關文章深入理解。

變量提升其實就是函數(shù)運行的編譯階段匙握,把所有var聲明的變量統(tǒng)一提升到該作用域“頂部”咆槽, 并賦默認值undefined。

所以執(zhí)行d()函數(shù)的時候圈纺,相當于以下流程,先編譯再執(zhí)行

var a = undefined
console.log(a)
a = 11

而dd()執(zhí)行的時候其實就是按照上面說的秦忿,由于dd上下文沒有聲明b變量,根據(jù)作用域鏈查找外部引用蛾娶,直到首次找到b灯谣,而作用域在編譯階段就確定了外部引用。具體可以參考下圖:

d方法運行時.png

所以蛔琅,就例子而言無論d方法還是dd方法胎许,它們的外部引用都是指向全局上下文,在執(zhí)行階段罗售,如果發(fā)現(xiàn)函數(shù)作用域沒有變量聲明就會沿著作用域往外部引用查找辜窑。

總結(jié)一下
1、js運行時有兩個階段:編譯階段 和 執(zhí)行階段
2寨躁、變量提升的根本原因是js在編譯階段確定的
3穆碎、執(zhí)行上下文有變量環(huán)境與詞法環(huán)境,變量環(huán)境存儲var聲明的變量朽缎,詞法環(huán)境存儲let cosnt聲明的變量惨远。
4谜悟、每個作用域的外部引用在編譯階段根據(jù)代碼的位置確定话肖。

v8引擎角度看javascript運行時

上面說到js運行時有編譯階段 和 執(zhí)行階段兩個階段,那么再從js引擎的角度來看葡幸,這是怎么一回事最筒。

首先先了解一些概念:

編譯器和解釋器
之所以存在編譯器和解釋器,是因為機器不能直接理解我們所寫的代碼蔚叨,所以在執(zhí)行程序之前床蜘,需要將我們所寫的代碼“翻譯”成機器能讀懂的機器語言。

按語言的執(zhí)行流程蔑水,可以把語言劃分為編譯型語言和解釋型語言邢锯。編譯型語言在程序執(zhí)行之前,需要經(jīng)過編譯器的編譯過程搀别,并且編譯之后會直接保留機器能讀懂的二進制文件丹擎,這樣每次運行程序時,都可以直接運行該二進制文件,而不需要再次重新編譯了蒂培。比如 C/C++再愈、GO 等都是編譯型語言。而由解釋型語言編寫的程序护戳,在每次運行時都需要通過解釋器對程序進行動態(tài)解釋和執(zhí)行翎冲。比如 Python、JavaScript 等都屬于解釋型語言媳荒。

解釋器抗悍、編譯器 語言流程

了解上面的概念之后,v8引擎就是走的基于解釋器的路線钳枕,但是又與它不同檐春,是一個改進版。具體如下圖

v8引擎處理代碼流程.png

從圖中可以看出v8是解釋器么伯、編譯器一起用了的疟暖。

通常,如果有一段第一次執(zhí)行的字節(jié)碼田柔,解釋器 Ignition 會逐條解釋執(zhí)行俐巴。解釋器 Ignition 除了負責生成字節(jié)碼之外,它還有另外一個作用硬爆,就是解釋執(zhí)行字節(jié)碼欣舵。在 Ignition 執(zhí)行字節(jié)碼的過程中,如果發(fā)現(xiàn)有熱點代碼(HotSpot)缀磕,比如一段代碼被重復執(zhí)行多次缘圈,這種就稱為熱點代碼,那么后臺的編譯器 TurboFan 就會把該段熱點的字節(jié)碼編譯為高效的機器碼袜蚕,然后當再次執(zhí)行這段被優(yōu)化的代碼時糟把,只需要執(zhí)行編譯后的機器碼就可以了,這樣就大大提升了代碼的執(zhí)行效率牲剃。

回到上面的js運行時兩個階段遣疯,編譯階段和執(zhí)行階段,編譯階段就是源碼 ->AST -> 字節(jié)碼凿傅。執(zhí)行階段就是基于字節(jié)碼缠犀、機器碼執(zhí)行。

最后

好了聪舒,以上就是javascript運行時的內(nèi)容辨液,了解這一過程希望對你開發(fā)過程有所幫助。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末箱残,一起剝皮案震驚了整個濱河市滔迈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖亡鼠,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赏殃,死亡現(xiàn)場離奇詭異,居然都是意外死亡间涵,警方通過查閱死者的電腦和手機仁热,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來勾哩,“玉大人抗蠢,你說我怎么就攤上這事∷祭停” “怎么了迅矛?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長潜叛。 經(jīng)常有香客問我秽褒,道長,這世上最難降的妖魔是什么威兜? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任销斟,我火速辦了婚禮,結(jié)果婚禮上椒舵,老公的妹妹穿的比我還像新娘蚂踊。我一直安慰自己,他們只是感情好笔宿,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布犁钟。 她就那樣靜靜地躺著,像睡著了一般泼橘。 火紅的嫁衣襯著肌膚如雪涝动。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天侥加,我揣著相機與錄音捧存,去河邊找鬼。 笑死担败,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的镰官。 我是一名探鬼主播提前,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼泳唠!你這毒婦竟也來了狈网?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拓哺,沒想到半個月后勇垛,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡士鸥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年闲孤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片烤礁。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡讼积,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出脚仔,到底是詐尸還是另有隱情勤众,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布鲤脏,位于F島的核電站们颜,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏猎醇。R本人自食惡果不足惜掌桩,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望姑食。 院中可真熱鬧波岛,春花似錦、人聲如沸音半。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽曹鸠。三九已至煌茬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間彻桃,已是汗流浹背坛善。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留邻眷,地道東北人眠屎。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像肆饶,于是被迫代替她去往敵國和親蚯妇。 傳聞我的和親對象是個殘疾皇子候学,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359