<script> /* js的解析過程,很有意思的一個東西 */ //一階段 var a = 5; function f(n){ alert(a); } f(); /* 上面代碼的全局處理過程: 1、預處理階段 a、讀取分析整個源代碼 b、先掃描函數聲明,之后掃描變量(var聲明) b_a、處理函數聲明時有沖突,會覆蓋 b_b、處理變量聲明時有沖突,會忽略 c、將掃描到的函數和變量保存到一個對象中(全局的保存到window對象中) d、變量的值是undefined,函數的值則指向該函數(是一個函數字符串) 形式如:window = {a : undefined, f : 'function(){alert(a);var a = 5;}'} 2、運行階段 在我們剛剛的案例中 a、將變量a的值從undefined改為5 b、調用f(),以便函數得到執行 上面函數(f)內,代碼的處理過程: 1、預處理階段 a、將函數的參數添加到一個對象(暫定為:詞法對象) b、掃描函數聲明,之后掃描變量(var聲明) d、將掃描到的函數和方法添加到詞法對象里面 c、變量的值是undefined,函數的值則指向該函數(與全局的一樣) 2、運行階段 與全局的的運行原理一樣 */ //二階段 var b = 1; function ff(){ alert(b); var b = 5; alert(b); } ff(); //結果彈出為:undefined, 5 /* 原因: js在預處理階段時,將函數ff()和變量b保存到window對象中, 此時b = undefined,到了運行階段,b = 1,這時調用函數ff(), js會先把函數內的變量添加到詞法對象中,此時b = undefined, 再之后alert(b),因為是在方法內部,所以alert(b)會調用詞法 對象中的b。然而這時詞法對象中的b = undefined,所以第一個alert執行結 果彈出的是undefined,當alert執行完之后b = 5,故第二個alert結果是5; */ //三階段 alert(a); function a() { console.log("xx"); } var a = 5; function a() { console.log("yy"); } //運行結果:'function a() { console.log("yy"); }' /* 原因: 我們發現變量a和兩個方法a()同名了,這時,js在預處理的時候 會優先將函數保存到window對象中,然后如果發現同名的是 變量,這時它會忽略這個變量;如果發現同名的是函數,那 么后面的會將前面的覆蓋。所以執行alert彈出的會是第二個函數a */ /*************************************************************/ alert(b); var b = 5; var b = function () { console.log("xx"); } //運行結果:undefined /* 原因: 我們知道,定義一個函數有多種形式。像上面這個案例中, 我們的函數是匿名的,然后賦值給了一個變量。但變量終究 是變量,js不會因為它的值比較特別就特殊對待,所以,js 在預處理的時候,先將第一個變量b保存到window中,此時 變量b=undefined,然后第二個變量b覆蓋了第一個變量,此時 的變量b依然還是等於undefined,所以在程序運行的時候彈出 值會等於undefined。 */ function c(num1){ alert(num1); } c(2); //運行結果:2 function d(num2){ alert(num2); var num2 = 5; } d(2); //運行結果:2 /* 原因: 在運行前,我就猜想彈出的這個應該是一個undefined的 可沒想到卻是2,這使我百思不得其解。於是請教老師得 出答案。 在js預處理的時候讀取到了這個函數有一個參數,於是就 直接將這個參數放到了詞法對象中,這是這個參數的值是 undefined,之后它繼續向下掃描,發現有一個變量定義, 但我們卻發現這變量與參數同名,這個時候js會怎么做? 這時按照之前所學的,這個變量會被加到詞法對象中,而 事實上也的確是加了,不過卻給它打上了一個標簽,用來 標識這個變量是一個參數,這時這個變量的值也是undef- ined。當程序真正運行的時候,我們把參數傳過去,這個 參數就會賦值的到這個參數中,然后彈出結果,然后再賦 值為5。 接下來還有幾個問題 1.看下面代碼 funciton f(num){ alert(num); funciton num(){ } } f(6); 返回結果為:'funciton num(){}' 像出現上面這個情況的時候,js也還是一樣在預處理的時 候,將參數放到詞法對象中,然后發現里面有一個同名的 函數,這時js就會把這個函數放到詞法對象中,並覆蓋之 前的參數,而它的值指向的就是這個函數。當我們程序真 正運行時,我們把參數傳過去,js在這里並不會把6這個參 數值賦值給這個形參。
</script>