1. 程式人生 > >瀏覽器的預解析過程

瀏覽器的預解析過程

優先級 為什麽 pre 後處理 來看 comm sdn data body

瀏覽器的預解析過程

題目:

var foo;
function foo(){}
console.log(foo);
  • 1
  • 2
  • 3
  • 4

結果是函數體function foo(){}
接著下面一道題:

function foo(){}
var foo;
console.log(foo);
  • 1
  • 2
  • 3

結果也是函數體function foo(){}

所有就有很多人說,函數聲明的優先級大於變量聲明的優先級。那麽,為什麽呢?這就要從瀏覽器的預解析說起了。

預解析流程

  1. 搜尋預解析關鍵字
    • 尋找var關鍵字
    • 尋找function關鍵字
  2. 執行預解析
    • 先應用var關鍵字聲明的標識符,使這些標識符有定義
      • 標識符有定以後,使用這項標識符就不會報錯了
      • 但因為沒有賦值,因此其值為undefined
    • 至此標識符中保存了函數的引用

幾個需要註意的細節

  • var 關鍵字對同一個標識符重復使用時,除第一次有效外,其他均做忽略處理。
  • 預解析時先處理變量聲明,再處理函數聲明
  • 不要糾結誰的優先級高,這些只是表面現象
  • 懂得了預解析流程,一切都是浮雲

看了預解析原理以後,下面咱們回到本文開頭的兩題,分析下預解析的過程,詳細的了解為什麽函數的優先級高於變量的優先級。follow me—->

先看第一個

var foo;
function foo(){}
console.log(foo);
  • 1
  • 2
  • 3

預解析過程為:

var foo;<----變量聲明的var
var foo;<----函數聲明抽出的var
foo=function (){}<----函數聲明抽出的賦值
console.log(foo);
  • 1
  • 2
  • 3
  • 4

再來看第二個,

function foo(){}
var foo;
console.log(foo);
  • 1
  • 2
  • 3

預解析過程為:

var foo;<----變量聲明的var
var foo;<----函數聲明抽出的var
foo=function (){}<----函數聲明抽出的賦值
console.log(foo);
  • 1
  • 2
  • 3
  • 4

比較這兩個,你發現了什麽?原來他們的預解析過程一樣啊,這也就是為什麽函數優先級高於變量的原因了。


如果你理解了上面的內容,那麽下面再出一個題:

var a=1;
function a(){}
console.log(a);
  • 1
  • 2
  • 3

這個瀏覽器是如何解析的呢?下面來跟著我的思路一起走:
1. 解析器首先搜尋var 關鍵字,結果第一行就發現了,把它提取到開頭。
2. 解析器搜尋function關鍵字,第二行發現了,首先分離var+函數名,此時發現和第一步的一樣,不做處理,然後開始分離函數的賦值,也就是a=function (){},此時a為函數體。
3. 解析器接著處理變量的賦值,a=1,上一步的函數體被覆蓋掉,此時a=1。
4. 最後處理console.log(a),自然而然的結果為1。

下面是解析器處理的代碼過程:

var a;<----變量聲明的var
var a;<----函數聲明抽出的var
a=function (){}<----函數聲明抽出的賦值
a=1;
console.log(a);
  • 1
  • 2
  • 3
  • 4
  • 5

瀏覽器的預解析過程