經過這一段代碼,讓咱們從新認識JavaScript

問題

請說明一下對這一段JavaScript的理解,主要包括引擎、編譯、執行、做用域、異常這些要點。而後猜想下會輸出那些內容。函數

var hello = null;
var b = 2;
foo(3);
console.log(c);

function foo(a){
 try{
    console.log(c);
 }catch(error){
    console.log(error);
 }
 try{
    hello();
 }catch(error){
    console.log(error);
 }
 c = a*b;
 console.log(a+b);
}

理解

編譯

/*
    1.編譯器遇到 var hello這個聲明語句,就在當前做用域中聲明變量hello(當前做用域沒有變量hello,這裏當前做用域就是全局做用域)。
*/
var hello = null;
var b = 2;
foo(3);
console.log(c);
/*
    1.編譯器在當前做用域把foo聲明成一個函數,同上
    2.在函數的內部做用域聲明a變量
*/
function foo(a){
 try{
    console.log(c);
 }catch(error){
    console.log(error);
 }
 try{
    hello();
 }catch(error){
    console.log(error);
 }
 c = a*b;
 console.log(a+b);
}

編譯器會先找到全部的聲明(var xxx,function xxx這些纔是聲明),而後在對應的做用域中建立該變量/函數,若是該聲明不存在的話。這個過程叫‘提高’。code

運行

/*
    1.運行時讀取到的是hello = null,首先在做用域鏈中查找hello,找到的話執行賦值操做
*/
var hello = null;
var b = 2;
/*
    1.在做用域鏈中找foo而且執行它,這裏隱式地執行了a = 3,這裏的a其實是foo函數做用域裏聲明的一個變量
    2.以後轉入函數內部執行
*/
foo(3);
/*
    0.在函數執行完畢後,執行到這兒
    1.在做用域中查找console這一變量,而後找到了,而後獲取它的log屬性,而後把它做函數執行
    2.隱式地執行了x = c,在當前做用域中查找c,能找獲得嗎?
*/
console.log(c);

function foo(a){
 try{
    //嘗試在做用域鏈中找c,找到本函數做用域-->全局做用域都沒找到,因而拋出異常ReferenceError,這個異常就是在做用域鏈中找不到某變量但又須要知道它的值出現的,咱們須要輸出c的值
    console.log(c);
 }catch(error){
    console.log(error);
 }
 try{
    //嘗試在做用域鏈中找hello,在全局做用域找到了,把它當函數執行,但它不是函數,因而拋出異常TypeError,這個異常就是找到了,可是使用方法不對
    hello();
 }catch(error){
    console.log(error);
 }
   //先計算a*b,在做用域鏈中找a和找b的值,而後執行c=6,又開始找c,想要給c賦值,找到頭也找不到,因而自動地在全局做用域下聲明瞭一個c,而後執行c=6,注意這裏咱們不關心c的值
 c = a*b;
 console.log(a+b);
}

js的做用域是詞法做用域,就是說變量處於哪一個做用域是由代碼怎麼寫決定的,在編譯期間肯定。
做用域鏈就像個大樓,查找變量的時候從當前樓層查到頂樓(全局)爲止ip

經過這段代碼可大體理解js引擎在編譯階段作了什麼,在執行階段又怎麼作,做用域在這兩個階段中起到什麼做用(中間者,管家)。兩個很是常見的異常是在什麼狀況下發生的。
・゜゚・:.。..。.:・'(゚▽゚)'・:.。. .。.:・゜゚・作用域

參考書籍《你不知道的JavaScript(上卷)》第一部分,亞馬遜電子書9.9元,強力推薦編譯器

相關文章
相關標籤/搜索