這次帶給大家基礎的JavaScript知識總結,總共有十一個知識點,基礎的JavaScript知識總結(八)預編譯執行過程下面就是實戰案例,一起來看一下。
JS運行三部曲
第一步:語法分析
第二部:預編譯
第三部:解釋執行
預編譯
語法分析也叫語意分析,文法分析他是通篇執行的一個過程,例如我寫了好多行程式碼,這些程式碼在執行的時候他是解釋一行執行一行,但是在執行之前系統執行的第一步它會掃描一遍,看看有沒有低級的語法錯誤,比如少些個括號,帶個中文之類的,它會通篇掃描一遍,但不執行,這個通篇掃描的過程叫語法分析,通篇掃描之後它會預編譯,然後在解釋一行執行一行,也就是解釋執行
預編譯前奏
imply global 暗示全局变量: 即任何变量,如果变量未经声明就赋值,自变量就位全局对象所有 eg : a = 123; eg : var a = b = 123;
一切宣告的全域變數,全是window的屬性
eg:var a = 123;===> window.a = 123; //例子: function test (){ console.log("a"); } test();//成功打印出a, box();//写在方法之前也成功打印出a,为什么能执行就是有预编译的过程 function box (){ console.log("a"); } var a =123; console.log(a);//输出123 console.log(a);//输出undefined,不报错; var a = 123; //但是如果直接打印会报错; console.log(b)//报错 //也是预编译的效果 //如果想偷懒记住两句话 //函数声明整体提升 //变量 声明提升
解釋一下函數宣告正題提升: 如果你寫一個函數宣告,不管你寫到哪裡,系統總是會把這個函數提到邏輯的最前面,所以你不管在哪裡調用,在上面調用也好,下面調用也罷,本質上他都是在函數的下面調用,他會把函數聲明永遠給你提升到邏輯的最前面
變數宣告提升例如
var a = 123;//其實他是兩部var a;//先宣告變數
a = 123;//在變數賦值
所以系統提升的變數而不是變數帶著值一起提升,所以在例子中a是印出undefined;
注意,這兩句話不是萬能的
例如
function a(a){ var a = 123; var a = function(){ } a(); }var a = 123;
這個就不是那兩句話可以解決的
在解釋上面的之前,要先用弄什麼是impiy global
imply globa:暗示全域變數: 即任何變數,如果變數未經宣告就賦值,自變數就位全域物件所有
eg : a = 123;
eg : var a = b = 123;
a = 10;console.log(a);//打印10然後在window屬性上有了awindow.a//10var b = 20;//你聲明了window也有bwindow就是全域的域
預先編譯正式
建立AO物件
找形參與變數宣告,將變數與形參名作為AO屬性名,值為undefined
將實參值和形參統一
在函數體裡面找函數宣告,值賦予函數體
function fn (a){ console.log(a); var a = 123; console.log(a); function a (){}; console.log(a); var b = function (){ } console.log(b); } fn(1);
這個例子,參數,變數,函數名字都叫a,首先可以確定的是肯定會發生一個覆蓋的現象,這樣子就很矛盾前面說了函數的預編譯執行在函數執行的前一刻,可以這樣子說,預編譯就把這些矛盾給調和了.
首先預先編譯的
第一步: 創建了一個AO物件,全名為Activation object 也就是作用域,也叫執行期上下文
AO{ }
第二步: 找形參和變數宣告,將變數和形參名作為AO屬性名,值為undefined
AO{ a : undefined b : undefined }
第三個步驟: 將實參值和形參統一
AO{ a : 1; b : undefined }
第四步: 在函數體裡面找函數宣告,值賦予函數體
AO{ a : 1, b : undefined, //b是是函数表达式,不是函数声明,所以不变 //然后有a了 有b了,然后将这个函数声明的名作为AO对象挂起来 d : }//然后值赋予函数体,也就是把a和b的属性值,变成函数体//覆盖掉a 和b的的属性值//也就变成下面的//因为第四步的优先级最高AO{ a : function a () {} b : undefined, //b是是函数表达式,不是函数声明,所以不变 d : function d () {} }
至此預編譯過程結束,開始執行程式碼,執行函數
#然後我們在看上面的範例
//预编译结果AO{ a : function a () {} b : undefined, d : function d () {} }//开始执行代码function fn (a){ //第一步开始打印a //根据上面预编译的结果, //所以打印结果是function a () {} console.log(a); //第二步执行 var a = 123; //因为在预编译的第二步里面,变量已经提升了 //所以第二步只执行的赋值 //a = 123;去AO对象里面去找a //也就变成 //AO{ //a : 123 这个才是a的存储值 //b : undefined, //d : function d () {} //} var a = 123; //所以打印出123 console.log(a); //因为这句在话在预编译的时候系统已经看了 //所以不在看这句话 function a (){}; //所以下面的console.log(a) //还是打印123; console.log(a); //一样下面的var b这句话在预编译的时候已经看了,所以不在看 //AO{ //a : 123 //所以b的值变成function(){} //b : function(){} //d : function d () {} //} var b = function (){ } //所以打印出function(){} console.log(b); }
fn(1);
我們在看個例子
function test(a , b){ console.log(a); c = 0; var c; a = 3; b = 2; console.log(b); function b () {} console.log(b); }//这下我们就很快的得出打印的东西//a-->1//b-->2//b-->2
預編譯不只會在函數體裡面,也會發生在全域裡面
全域裡面的第一步是先生成GO Global Object,其他一樣
GO === window
那麼問題來了是GO先還是AO先
答案是先執行GO
相信看了本文案例你已經掌握了方法,更多精彩請關注php中文網其它相關文章!
相關閱讀:
基礎的JavaScript知識總結(六)函數、初始作用域(上)
基礎的JavaScript知識總結(六)函數、初始作用域(下)
以上是基礎的JavaScript知識總結(八)預編譯執行過程的詳細內容。更多資訊請關注PHP中文網其他相關文章!