js的解析與執行過程

1:預處理階段

當輸入如下代碼時候

var a = 1;
function crli(){
    alert(a);
}
crli()//1

結果爲 1

當改變下面代碼時候

var a = 1;
function crli(){
    alert(a);
    var a = 5;
}
crli()//undefined

結果爲 undefined

這是爲什麼呢?

js解析與執行過程一共有2個階段,一個預處理階段,一個是執行階段(可以看成全局預處理階段和執行階段,以及函數預處理階段和執行階段)

當js解析代碼時候,會先創建一個lexical environme這麼一個對象,然後掃描js代碼兩個部分:
一個是用聲明方式創建的函數,
另一個是用var 定義的變量,
然後把函數和變量的名字加到lexical environme中,比方說

1 . 全局狀態

lexical environme(**全局的環境對象===window**)
{
    a:undefined
    crli:對函數的一個引用
}

var a =5;
b = 1;
function crli(){

}

如果非函數聲明、非var方式聲明的變量,則預處理階段不會將函數和變量的名字加到lexical environme中
例子1:

a();//aa
b();//b is not a function

function a() {
    console.log("aa");
}
var b = function b(){
    console.log("bb");
}

lexical environme
{
    a:對函數的一個引用
    b:undefined
}

例子2:

console.log(a);//undefined
console.log(b);//b is not defined
var a = 1;
b = 2;

lexical environme
{
    a:undefined
}

當遇到函數聲明有衝突時候後者會覆蓋前者,
變量聲明有衝突時候,會忽略

alert(f);//function f(){console.log("s");}
function f(){
    console.log("s");
}
var f = 5;
window
{
    f:指向函數
}
alert(f);//function f(){console.log("q");}
function f(){
    console.log("s");
}
var f = 5;
function f(){
    console.log("q");
}
window
{
    f:指向函數
}

2 . 函數狀態

function f(a,b){
    alert(a);
    alert(b);
    var b = 100;
    function a(){
    }
}
f(1,2)//function a(){}
      //2

當遇到函數聲明有衝突時候後者會覆蓋前者,
變量聲明有衝突時候,會忽略

lexical environme           lexical environme
{                           {
    a:1                          a:指向函數
    b:2             ==>          b:2
    arguments:                   arguments:
}                           }

此時解釋

var a = 1;
function crli(){
    alert(a);
    var a = 5;
}
crli()//undefined
window 
{
    a : 1
    crli:指向函數
}
lexical environme 
{
    a:undefined
}

函數預處理
執行時,alert(a) 所以是undefind

發佈了38 篇原創文章 · 獲贊 10 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章