首頁 >web前端 >js教程 >基礎的JavaScript知識總結(八)預編譯執行過程

基礎的JavaScript知識總結(八)預編譯執行過程

php中世界最好的语言
php中世界最好的语言原創
2018-03-10 13:31:331771瀏覽

這次帶給大家基礎的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知識總結(七)遞迴

以上是基礎的JavaScript知識總結(八)預編譯執行過程的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn