深刻理解javascript引擎對於腳本的處理

腳本處理模型

javascript的基本特色


  1. js是一門至關簡單的運行時解釋語言。javascript

  2. 對象模型很直接也沒有類的概念。html

  3. 有自動垃圾回收。java

  4. 弱數據類型。編程

  5. 動態類型(dynamic typing):運行的時候才肯定對象的類型。瀏覽器

  6. javascript沒有內置的I/O機制。框架

擴展:javascript程序與宿主環境進行交互,是經過一系列預約義的方法和屬性實現的,這些方法和屬性會再映射成瀏覽器的內部原生代碼,因此與其餘很對常規的編程語言不一樣,瀏覽器開放的這些藉口每每受限且有針對性。編程語言

腳本處理模型

首先,不管是獨立的窗口仍是在框架裏面,每一個展現在瀏覽器裏面的html文檔,都被賦予了一個獨立的javascript執行環境實例,在這個環境裏面加載的腳本的全部全局變量和函數都擁有一個獨立的命名空間。函數

而後,同一個文檔的全部腳本都運行在同一個執行環境裏面,共享同一個沙箱,而且可以經過瀏覽器提供的API與其餘上下文環境交互。spa

最後:在特定的執行上下文裏面,每段javascript代碼塊都是自成體系處理的,順序也基本肯定。每段代碼塊都是由若干符合語法格式的獨立單元組成,處理的過程包括清晰並且連續的三個步驟:源碼處理,函數解析,代碼執行。命令行

源碼處理

源碼處理階段會檢查腳本代碼塊裏面的語法,一般會先把代碼轉換成中間層的二進制映像,這樣才能或獲得使人滿意的執行速度。在完全完成這一步驟以前,這些二進制代碼對全局並沒有影響。若是源碼處理階段出錯,整個有問題的代碼塊都會被棄用;而後解析器會繼續處理下一段代碼塊。

函數解析

完成了上一步驟以後,接下來就是解析器對當前代碼塊裏全部具名的全局函數進行識別並註冊。在這一階段完成以後,這些函數才能被執行代碼所調用。

對於代碼

<script>
hello_world();

function hello_world(){
    console.log('hello, man');
}
</script>



由於javascript在執行前會額外預處理,所以上面的寫法會成功執行。

而對於代碼

<script>
hello_world();
</script>

<script>
function hello_world(){
    console.log('hello, man');
}
</script>



對於這段代碼會由於運行的時候錯誤而執行失敗,由於代碼裏每段獨立的代碼塊並非同時處理的,這是根據javascript引擎讀取代碼塊的前後順序決定的。在執行第一個代碼塊的時候,定義hello_world()的那塊代碼塊尚未被解析呢。

再看代碼

<script>
hello_world();

var hello_world = function(){
    console.log('hello, men');
}
</script>



出現這個現象的緣由是:在調用hello_world()的時候,對於hello_world變量的賦值尚未開始呢!

解釋:javascript這種全局名稱解析模型只針對於函數有效,而對於變量的聲明卻並不是如此。與其餘腳本語言相似,變量是按照執行的時候出現的順序註冊的。

代碼執行

一旦函數解析階段也執行完畢了,javascript引擎就會開始順序執行在函數區塊以外的全部代碼。若是在執行過程當中,因爲某些未處理的異常或者一些偏門的緣由,腳本的執行可能會失敗。若是碰上了這個錯誤,那些已經被正確解析的函數仍然能被調用,而已經執行過的代碼的結果,對此上下文環境也仍然有效的。

<script>
function no_called(){
  console.log('這個函數不會被執行,由於沒有被調用到!');
}

function hello_world(){
  console.log('這個函數只有在被調用到的時候纔會被執行。效果是在命令行中出現這句話,而後拋出一個異常:由於調用了一個沒法解析的函數');
  do_stuff();
}

console.log('整個程序會從這行代碼開始執行!');

hello_world();

console.log('這行代碼不會被執行到,由於hello_world()會觸發一個未處理的異常。');
</script>

<script>
  console.log('以前的異常是不會影響到這行獨立區塊的代碼的,因此可以運行。')
</script>



從中咱們能夠看到:因爲出現了未預期和未處理的某些異常狀況,因此程序的運行會帶來一些出人意外的後果:此時整個應用的狀態會變得不太統一,實際上即便有異常,代碼也仍然有可能繼續執行。

異常的本意是阻止未能預期的錯誤,不會再擴大這種錯誤的影響,因此javascript這樣的設計頗爲古怪。

相關文章
相關標籤/搜索