最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

入門小白基礎(chǔ)篇之JavaScript預(yù)編譯詳解

 更新時(shí)間:2026年05月29日 10:51:04   作者:biubiubiu_LYQ  
js中的預(yù)編譯是指在代碼被執(zhí)行前解釋器對(duì)代碼進(jìn)行的操作,這篇文章主要介紹了入門小白基礎(chǔ)篇之JavaScript預(yù)編譯的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

在了解預(yù)編譯之前,我們應(yīng)該先了解一下v8引擎是怎樣工作的,首先它需要將代碼分成一個(gè)個(gè)詞法單元,如 'var' ,'a',等,再進(jìn)行語法分析,將詞法單元組成 AST(抽象語法樹),最后根據(jù)AST生成代碼執(zhí)行。那么預(yù)編譯就是發(fā)生在代碼執(zhí)行之前,讓我們來看一個(gè)例子。

console.log(a);  //輸出 undefined
var a = 1

按照大家所理解的代碼執(zhí)行步驟,應(yīng)該是從上到下依次執(zhí)行,那么它應(yīng)該報(bào)錯(cuò),但是最后顯示的是undefined,這是為什么呢?這是因?yàn)樵诖a執(zhí)行之前,它先進(jìn)行了編譯這個(gè)過程,那編譯是怎么做呢?

var a  //定義變量 a  將它提升到當(dāng)前作用域的頂部
console.log(a); // 得到undefined  找不到a的值
a = 1 

將變量提升到當(dāng)前作用域的頂部,這個(gè)過程我們稱之為聲明提升,此處為全局作用域,所以得到輸出結(jié)果為undefined,那為什么出現(xiàn)聲明提升呢?我們就要具體了解一下預(yù)編譯過程是怎么樣的。

預(yù)編譯

預(yù)編譯發(fā)生在代碼執(zhí)行之前,它分為兩類 函數(shù)體內(nèi)的預(yù)編譯和全局預(yù)編譯,函數(shù)的預(yù)編譯是在函數(shù)被調(diào)用時(shí)才觸發(fā),而全局預(yù)編譯是在代碼加載時(shí)就觸發(fā)了,那它們有以下幾個(gè)步驟。

1.函數(shù)體內(nèi)的預(yù)編譯

  1. 創(chuàng)建一個(gè)執(zhí)行上下文 AO:{}
  2. 找形參和變量聲明,將形參和變量名作為屬性名,添加到AO中,值為 undefined
  3. 將形參和實(shí)參統(tǒng)一
  4. 在函數(shù)體內(nèi)找函數(shù)聲明,將函數(shù)名作為AO 中的屬性名,函數(shù)體作為屬性值

讓我們來看一個(gè)例子,根據(jù)步驟依次梳理

function fn(a) { 
  console.log(a); 
  var a = 123 
  console.log(a);
  function a() {}
  var b = function() {}
  console.log(b);
  function c() {}
  var c = a
  console.log(c);
}
fn(1)  //調(diào)用函數(shù) 

首先 創(chuàng)造一個(gè)執(zhí)行上下文 AO:{}

其次 找到形成和變量聲明,將形參和變量名作為屬性名,添加到AO中,也就是說找到 形參a 變量a b c 添加到AO中, 值為 undefined,即有

AO = {
a:undefined  //出現(xiàn)了形參a 又出現(xiàn)變量a 則進(jìn)行覆蓋 對(duì)象中只有一個(gè)key
b:undefined 
c:undefined 
}

然后將 將形參和實(shí)參統(tǒng)一那么 a此時(shí) 值為1,即有

AO = {
a:undefined →1
b:undefined 
c:undefined 
}

最后找到在函數(shù)體內(nèi)找函數(shù)聲明,將函數(shù)名作為AO 中的屬性名,函數(shù)體作為屬性值即有

AO = {
a:undefined →1→function a(){}
b:undefined 
c:undefined→function c(){}
}

已經(jīng)完成預(yù)編譯過程,那就開始執(zhí)行代碼,所以有

function fn(a) { 
  console.log(a); //                         輸出結(jié)果 function a(){}
  var a = 123  // 把123賦值給a
  console.log(a); /                          輸出 a值為123
  function a() {}
  var b = function() {} 把function(){} 賦給b
  console.log(b); //                         輸出為 function(){}
  function c() {}
  var c = a  //把a(bǔ)賦給c c為123
  console.log(c); //                        輸出123
  
// AO = {
// a:undefined →1 →function a(){} →123
// b:undefined → function b(){}
// c:undefined →function c(){} →123

}
fn(1)  //調(diào)用函數(shù) 

結(jié)果也正如我們所判斷的這樣

2.全局預(yù)編譯

  1. 創(chuàng)建全局執(zhí)行上下文 GO:{}
  2. 找全局變量聲明,將全局變量名作為屬性名,添加到GO中,值為 undefined
  3. 找全局函數(shù)聲明,將函數(shù)名作為GO 的屬性名,函數(shù)體作為屬性值

依舊來看一個(gè)例子,根據(jù)步驟依次梳理

var a 
var b = 2
function a(){
    console.log(a);
    var c = 3
    var a = b
    function c(){}
    console.log(c);
}
a()
console.log(a);

首先,創(chuàng)建全局上下文GO:{}

其次,找全局變量聲明,將全局變量聲明作為屬性名,添加到GO中,也就說將變量 a,b添加到GO中,值為undefined,即有

GO = {
    a: undefined, 
    b: undefined
}

最后,找全局函數(shù)聲明,將函數(shù)名作為GO 的屬性名,函數(shù)體作為屬性值,即有

GO = {
    a: undefined →function a(){xxx}, 
    b: undefined
}

全局編譯已經(jīng)完成,開始執(zhí)行代碼,所以有

//GO = {
//    a: undefined →function a(){xxx}, 
//    b: undefined
//}

var a 
var b = 2   // 把 2 賦給 b
function a(){
    console.log(a);
    var c = 3
    var a = b
    function c(){}
    console.log(c);
}
a() //調(diào)用函數(shù) function a(){}
console.log(a);  //輸出 function a(){}

所以 11 行處代碼 輸出為function a(){},而代碼 有a(),說明調(diào)用了函數(shù)function a(){xxx},那我們又需要對(duì)函數(shù)進(jìn)行預(yù)編譯,與上文步驟相同,所以我們可以得到

//GO = {
//    a: undefined→ function a(){xxx}, 
//    b: undefined
//}

var a 
var b = 2
function a(){

// AO = {
//   c: undefined→ function c(){}→ 3
//   a: undefined→ b 即 2
//}
  
    console.log(a);               //輸出 undefined
    var c = 3   // 把3賦給c
    var a = b // 把b的值賦a 函數(shù)中沒有,去外層找,得到b值為2 即a值為 2
    function c(){}  
    console.log(c);               //輸出 3
}
a()
console.log(a);                  //輸出 function a(){}

理解之后結(jié)果也是清晰明了起來

全局預(yù)編譯GO與函數(shù)體內(nèi)預(yù)編譯AO的關(guān)系

1. 執(zhí)行順序:先全局預(yù)編譯 → 再函數(shù)調(diào)用時(shí)執(zhí)行函數(shù)預(yù)編譯

2. 作用域?qū)蛹?jí):全局是最外層,代碼執(zhí)行時(shí)開始編譯→函數(shù)預(yù)編譯依附全局,形成層級(jí)作用域,只有當(dāng)調(diào)用函數(shù)時(shí)才會(huì)開始編譯

3. 優(yōu)先級(jí):函數(shù)內(nèi)部變量 > 全局變量,內(nèi)部優(yōu)先訪問自身預(yù)編譯內(nèi)容,找不到再去全局里面找,而全局找不到,不會(huì)去函數(shù)內(nèi)部找 即(小可以去大找,大不會(huì)去小找)

4. 互不沖突:同名變量互不覆蓋,只遵循作用域就近原則

到此這篇關(guān)于入門小白基礎(chǔ)篇之JavaScript預(yù)編譯的文章就介紹到這了,更多相關(guān)JS預(yù)編譯內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

汶川县| 安丘市| 汤阴县| 谷城县| 新蔡县| 涪陵区| 福建省| 宜兰市| 邛崃市| 安溪县| 云龙县| 赤水市| 阳新县| 梁河县| 抚宁县| 浮梁县| 小金县| 四会市| 裕民县| 沙河市| 东至县| 湟源县| 乌什县| 朝阳区| 沁水县| 留坝县| 永平县| 通化市| 财经| 安庆市| 北流市| 三原县| 金昌市| 海安县| 泊头市| 大姚县| 东源县| 道孚县| 石狮市| 措美县| 桐城市|