不知道,大家對語言中變數的“聲明”與“定義”是怎麼理解的,
我的理解如下:
“聲明”變數,只是僅僅聲明,而“定義”變數,指聲明了,並且賦值了。
例如:
複製代碼 代碼如下:var name;//只是聲明
var num = 11;//聲明,並且賦值,即定義了
var password = "yangjiang";//聲明,並且賦值,即定義了
下面是幾點總結:
變數的範圍:全域的和局部的。(注意:如果嘗試讀取一個未聲明的變數的值,javascript會產生一個錯誤)
第一點:在都使用var關鍵字修飾變數的情況下,如果給一個局部變數或函數的參數聲明的名字與某個全域變數的名字相同,
那麼就有效地隱藏了這個全域變數。
例如: 複製代碼 代碼如下:var scope1 = "global";//var修飾
function checksScope(){
var scope1 = "local";//var修飾
document.write(scope1);
}checksScope();//local
第二點:如果嘗試給一個未用 var 關鍵字聲明的變數,那麼,隱式聲明的變數總是被建立為全域變數,即使
該變數只在一個函數體內使用(只有該函數運行了,才會發生作用),注意不支援函數嵌套的情形。
例如: 複製代碼 代碼如下:scope2 = "globalAAAAA";//沒有使用var修飾(js會預設將其聲明為全域變數)
function checkScopeA(){
scope2 = "localAAAAA";//沒有使用var修飾(js會預設將其聲明為全域變數)
document.write("<br/>"+scope2);
myscope = "myLocalAAAAA";//沒有使用var修飾(js會預設將其聲明為全域變數)
document.write(","+myscope);
}
checkScopeA();//localAAAAA,myLocalAAAAA *A
document.write("<br/>"+scope2);//localAAAAA *B
document.write("<br/>"+myscope);//myLocalAAAAA *C
如果將上面的例子中的 *A處的代碼注釋掉,
例如: 複製代碼 代碼如下:scope2 = "globalAAAAA";//沒有使用var修飾(js會預設將其聲明為全域變數)
function checkScopeA(){
scope2 = "localAAAAA";//沒有使用var修飾(js會預設將其聲明為全域變數)
document.write("<br/>"+scope2);
myscope = "myLocalAAAAA";//沒有使用var修飾(js會預設將其聲明為全域變數)
document.write(","+myscope);
}
//checkScopeA(); *A
document.write("<br/>"+scope2);//globalAAAAA *B
document.write("<br/>"+myscope);//發生錯誤 *C
因為函數checkScopeA沒有執行,所以 *B處輸出為globalAAAAA;
因為函數checkScopeA沒有執行,所以變數myscope沒有聲明,如果嘗試讀取一個未聲明的變數,會發生錯誤。
第三點:
在javascript中,函數的定義是可以嵌套的。由於 每個函數都有它自己的局部範圍,所以有可能出現幾個局部範圍的嵌套層。
例如: 複製代碼 代碼如下:var scope3 = "global scope"; //定義了一個全域變數
function checkScopeB(){
var scope3 = "local scope"; //定義了一個局部變數,覆蓋了全域變數scope3
function nested(){
var scope3 = "nested scope"; //在函數的函數的內部,定義了一個局部變數
document.write("<br/>"+scope3); //nested scope
}
nested();
}
checkScopeB();//nested scope
第四點:
在javascript中,沒有塊級範圍,函數中聲明的所有變數,無論是在哪裡聲明的,在整個函數中它們都是有聲明的。
在javascript中,沒有塊級範圍,函數中定義的所有變數,無論是在哪裡定義的,在整個函數中它們都是有定義的。
例如: 複製代碼 代碼如下:function test(o){//根據以上的說明:此函數中的i,j,k三個變數的範圍是相同的。
var i = 0; //變數 i 在整個函數中都有定義
if(typeof o == "object"){
var j = 0 ; //變數 j 在整個函數中都有定義,而不僅僅是在 if 語句塊
for(var k=0;k<10;k++){//變數 k 在整個函數中都有定義,而不僅僅是在 if 語句塊
document.write("<br/>k的值為:"+k);
}
document.write("<br/>for迴圈外k的值:"+k);//此時的 k 仍然被定義了,k=10
}
document.write("<br/>j的值:"+j); //變數 j 被聲明了,但可能沒有被初始化 因為可能往函數中 傳入的參數 不是對象 ,if語句塊不會執行
}
下面通過兩種方式調用此函數:
方式一:傳入對象
test({});//輸出結果:上例中的注釋
方式二:什麼都不傳
test();//輸出結果:j的值:undefined
想不明白的是,在第二種方式中的輸出結果,為什麼會是 undefined。我當時猜的是:j的值:0
後來,這本書上面說:
由於局部變數在整個函數體內都是有聲明(或定義)的,這就意味著在整個函數體中都隱藏了同名的全域
變數。雖然 局部變數在整個函數體內中都是有聲明(或定義)的,但是在執行var語句之前,它是不會被初始化的。
這樣的話,上面的方式二調用的輸出結果,就比較好解釋了,由於變數j在整個函數中都有定義,而又由於傳入函數的參數為空白,所以函數體中的if語句不會執行,從而使得j的值為undefined.(這是我參照上面書上說的那句話的理解)
下面的例子,更好的說明: 複製代碼 代碼如下:var sssss = "全域變數";
function f(){
document.write("<br/>"+sssss);//輸出:undefined 而不是輸出"全域變數"
var sssss = "局部變數";
document.write("<br/>"+sssss);//輸出:局部變數
}