不知道,大家對語言中變量的“聲明”與“定義”是怎麼理解的,
我的理解如下:
“聲明”變量,只是僅僅聲明,而“定義”變量,指聲明了,並且賦值了。
例如:
復制代碼 代碼如下:
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);//輸出:局部變量
}