JavaScript預編譯(函式)

2021-09-03 02:17:16 字數 3626 閱讀 2178

知識點預習

1、js檔案的執行三部曲:語法分析、預編譯、解釋執行。

2、變數未經宣告就使用,系統會報錯。

3、var aa = "夫_子":變數的宣告和賦值,aa為變數名,"夫_子"是變數值。var aa是變數的宣告,aa = "夫_子"是變數賦值。

4、函式宣告:function demo(){}。函式表示式:var demo=function(){}

js檔案在執行的最開始,會將檔案整體掃瞄一遍,檢查是否含有最基本的語法錯誤,比如,含有中文符號、關鍵字單詞拼寫錯誤等等最基本的語法錯誤,此為語法分析。

test();//夫_子

function test()

test();//夫_子

console.log(a);//undefined

var a=123;

console.log(a);//123

b();//uncaught typeerror: b is not a function

var b=function()

b();//夫_子

console.log(c);//uncaught referenceerror: c is not defined

看上面的例子,函式的執行,不管是放在函式定義之前,還是函式定義之後,都能執行出正確的結果,但是如果按照js的語言執行規則來解釋,卻又解釋不通, 例如我們看到這裡test的執行在函式的上面,如果按照**的執行順序,應該先執行test,再創造函式,那麼顯然就會報錯,但此處卻沒有任何問題。

第二個和第三個是變數的定義,變數a和b在定義之後執行,沒有任何問題,但是在定義之前執行,卻出現了兩個不同的結果,a的執行結果是(undefined:未定義),沒有報錯,b的執行結果是(uncaught referenceerror: a is not defined:a沒有定義),系統報錯了。這一切都是為什麼呢,為什麼a不報錯而b報錯了呢,先別急,慢慢看,接下來才是重點。

造成這一切的根本原因,就是**執行前期的預編譯,那什麼是預編譯呢?

簡單來說,預編譯主要有兩點:一是變數、宣告提公升,二是函式整體提公升,提公升到語句執行邏輯的最前邊。賦值和邏輯操作會被留在原地等待執行,即使賦值語句即等號後邊是乙個函式體。這麼說,可能還是一知半解,甚至是完全看不懂,接下來例項講解。

預編譯四部曲:

1、建立ao物件:執行期上下文(activation object)

2、尋找形參和變數宣告,並且當做屬性放在ao物件裡,並賦值為undefined

3、將實參和形參統一

4、尋找函式宣告,值為函式體(此過程權重最高,如果和變數同名,會用函式體覆蓋變數)

function demo(a)  

var a="夫_子";

console.log(a);//夫_子

function a(){}

console.log(a);//夫_子

var b = function (){}//函式表示式

console.log(b); //function (){}

}demo(1)

/*預編譯期間,各變數值得變化

ao,b:undefined

}*/

1、建立ao物件:執行期上下文(activation object)

ao 2、尋找形參和變數宣告,並且當做屬性放在ao物件裡,並賦值為undefined ao

3、將實參和形參統一 ao

4、在函式體裡尋找函式宣告,值賦予函式體(此過程權重最高,如果和變數同名,會用函式體覆蓋變數)

ao,

b:undefined }

5、此函式在預編譯結束的時候,ao裡儲存的物件就是如下,在執行函式的時候,再根據語句情況,修改相應的變數值

ao,

b:undefined }

上邊的例子可以相對簡單一些,下面來乙個稍微複雜點的

function test(a,b)

console.log(b);//20

}test(5);

/*預編譯期間各變數值得變化

aoc:undefined

}*/

1、建立ao物件:執行期上下文(activation object)

ao2、尋找形參和變數宣告,並且當做屬性放在ao物件裡,並賦值為undefined

ao3、將實參和形參統一

ao4、在函式體裡尋找函式宣告,值賦予函式體

aoc:undefined

}5、此函式在預編譯結束的時候,ao裡儲存的物件就是如下,在執行函式的時候,再根據語句情況,修改相應的變數值

aoc:undefined

}

函式的預編譯過程,按照上面的四個步驟來進行,就不會出錯。函式的優先順序要比變數的優先順序高,這裡的優先順序不是誰在前邊,誰在後邊,而是在預編譯的過程中,如果變數名字和函式名一樣,那麼函式體會覆蓋變數的undefined。

js是一門解釋性語言,解釋型語言的程式沒有執行前的編譯過程,執行程式的時候才翻譯,會有乙個專門的直譯器負責在每個語句執行的時候解釋程式**。解釋一行執行一行。

函式在執行的前一刻,會建立乙個獨一無二的執行期上下文即ao,用來儲存函式執行過程中需要用到的變數和函式宣告,這個執行期上下文就是函式執行時的環境,在函式執行完畢之後,這個執行期上下文就會被銷毀(閉包單獨講解),下一次呼叫函式的時候,又會重新建立乙個新的執行期上下文。

函式在執行的時候,會根據函式的情況,修改ao中儲存的變數值,例如:第乙個例子中,函式執行到 var a="夫_子";語句時,會將ao中a的值修改為「夫_子」,有人可能會問,上邊a的值是乙個函式體function a(){},不是說,函式要比變數的優先順序高麼,那為什麼a=「夫_子」還是會覆蓋函式體。

在函式預編譯的時候,函式的優先順序要比變數的優先順序高,但是在函式執行的過程中,變數的賦值語句會覆蓋函式體。請看下邊的例子,至於這些到底是為什麼,這就是瀏覽器核心的解析規則了,

function a() {}

var a;

console.log(typeof a);//fuction,此時a指向函式。

var a;

function a() {}

console.log(typeof a);//function,此時a仍指向函式。

function a() {}

var a=5;

console.log(typeof a);//number,此時a等於5。

var a=5;

function a() {}

console.log(typeof a);//number,此時a等於5。

function test(a)

var a=5;

console.log(a);//5

console.log(b);//f b(){}

var b=function(){};

console.log(b);//f (){}//和上乙個b列印的函式,不是同乙個函式

function a(){}

function b(){}

}test(5)

JavaScript函式簡單理解(2) 預編譯

線理清楚幾個概念 函式的預編譯 一 什麼是預編譯 1 函式宣告的整體提公升 永遠會提公升在邏輯的最前邊 2 變數宣告的提公升 只是提公升了變數定義的語句,賦值語句是沒有提公升的 二 全域性變數和區域性變數 1 imply global 隱式全域性變數 及時乙個沒有經過宣告就被賦值的變數,可以在全域性...

javascript的預編譯階段

1.變數與函式 在js中宣告乙個變數有let const var三種方式,函式有宣告函式和函式表示式兩種。2.預編譯階段做的事情 在預編譯階段,所有的var宣告的變數會被初始化為undefined,所有的宣告函式會用它的定義進行初始化,而const let宣告的變數則不會在預編譯階段執行初始化,函式...

javascript基礎 預編譯 this指向

預編譯發生在函式執行前一刻,可以拆分成一下幾步 1 生成activation object 即ao物件 執行期上下文 2 查詢形參和變數,並將其作為ao物件的屬性,值為undefined 3 將實參的值賦給形參 4 在函式體內查詢函式宣告,並將值賦予函式體 看看下面的例子 function fn a...