<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>