知識點預習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...