javascript權(quán)威指南 學(xué)習(xí)筆記之變量作用域分享
更新時(shí)間:2011年09月28日 00:19:09 作者:
最近一直在看《javascript權(quán)威指南 第五版》,變量作用域這一章,看得真的有點(diǎn)累。不過(guò),收獲還是多多。
不知道,大家對(duì)語(yǔ)言中變量的“聲明”與“定義”是怎么理解的,
我的理解如下:
“聲明”變量,只是僅僅聲明,而“定義”變量,指聲明了,并且賦值了。
例如:
var name;//只是聲明
var num = 11;//聲明,并且賦值,即定義了
var password = "yangjiang";//聲明,并且賦值,即定義了
下面是幾點(diǎn)總結(jié):
變量的作用域:全局的和局部的。(注意:如果嘗試讀取一個(gè)未聲明的變量的值,javascript會(huì)生成一個(gè)錯(cuò)誤)
第一點(diǎn):在都使用var關(guān)鍵字修飾變量的情況下,如果給一個(gè)局部變量或函數(shù)的參數(shù)聲明的名字與某個(gè)全局變量的名字相同,
那么就有效地隱藏了這個(gè)全局變量。
例如:
var scope1 = "global";//var修飾
function checksScope(){
var scope1 = "local";//var修飾
document.write(scope1);
}checksScope();//local
第二點(diǎn):如果嘗試給一個(gè)未用 var 關(guān)鍵字聲明的變量,那么,隱式聲明的變量總是被創(chuàng)建為全局變量,即使
該變量只在一個(gè)函數(shù)體內(nèi)使用(只有該函數(shù)運(yùn)行了,才會(huì)發(fā)生作用),注意不支持函數(shù)嵌套的情形。
例如:
scope2 = "globalAAAAA";//沒(méi)有使用var修飾(js會(huì)默認(rèn)將其聲明為全局變量)
function checkScopeA(){
scope2 = "localAAAAA";//沒(méi)有使用var修飾(js會(huì)默認(rèn)將其聲明為全局變量)
document.write("<br/>"+scope2);
myscope = "myLocalAAAAA";//沒(méi)有使用var修飾(js會(huì)默認(rèn)將其聲明為全局變量)
document.write(","+myscope);
}
checkScopeA();//localAAAAA,myLocalAAAAA *A
document.write("<br/>"+scope2);//localAAAAA *B
document.write("<br/>"+myscope);//myLocalAAAAA *C
如果將上面的例子中的 *A處的代碼注釋掉,
例如:
scope2 = "globalAAAAA";//沒(méi)有使用var修飾(js會(huì)默認(rèn)將其聲明為全局變量)
function checkScopeA(){
scope2 = "localAAAAA";//沒(méi)有使用var修飾(js會(huì)默認(rèn)將其聲明為全局變量)
document.write("<br/>"+scope2);
myscope = "myLocalAAAAA";//沒(méi)有使用var修飾(js會(huì)默認(rèn)將其聲明為全局變量)
document.write(","+myscope);
}
//checkScopeA(); *A
document.write("<br/>"+scope2);//globalAAAAA *B
document.write("<br/>"+myscope);//發(fā)生錯(cuò)誤 *C
因?yàn)楹瘮?shù)checkScopeA沒(méi)有執(zhí)行,所以 *B處輸出為globalAAAAA;
因?yàn)楹瘮?shù)checkScopeA沒(méi)有執(zhí)行,所以變量myscope沒(méi)有聲明,如果嘗試讀取一個(gè)未聲明的變量,會(huì)發(fā)生錯(cuò)誤。
第三點(diǎn):
在javascript中,函數(shù)的定義是可以嵌套的。由于 每個(gè)函數(shù)都有它自己的局部作用域,所以有可能出現(xiàn)幾個(gè)局部作用域的嵌套層。
例如:
var scope3 = "global scope"; //定義了一個(gè)全局變量
function checkScopeB(){
var scope3 = "local scope"; //定義了一個(gè)局部變量,覆蓋了全局變量scope3
function nested(){
var scope3 = "nested scope"; //在函數(shù)的函數(shù)的內(nèi)部,定義了一個(gè)局部變量
document.write("<br/>"+scope3); //nested scope
}
nested();
}
checkScopeB();//nested scope
第四點(diǎn):
在javascript中,沒(méi)有塊級(jí)作用域,函數(shù)中聲明的所有變量,無(wú)論是在哪里聲明的,在整個(gè)函數(shù)中它們都是有聲明的。
在javascript中,沒(méi)有塊級(jí)作用域,函數(shù)中定義的所有變量,無(wú)論是在哪里定義的,在整個(gè)函數(shù)中它們都是有定義的。
例如:
function test(o){//根據(jù)以上的說(shuō)明:此函數(shù)中的i,j,k三個(gè)變量的作用域是相同的。
var i = 0; //變量 i 在整個(gè)函數(shù)中都有定義
if(typeof o == "object"){
var j = 0 ; //變量 j 在整個(gè)函數(shù)中都有定義,而不僅僅是在 if 語(yǔ)句塊
for(var k=0;k<10;k++){//變量 k 在整個(gè)函數(shù)中都有定義,而不僅僅是在 if 語(yǔ)句塊
document.write("<br/>k的值為:"+k);
}
document.write("<br/>for循環(huán)外k的值:"+k);//此時(shí)的 k 仍然被定義了,k=10
}
document.write("<br/>j的值:"+j); //變量 j 被聲明了,但可能沒(méi)有被初始化 因?yàn)榭赡芡瘮?shù)中 傳入的參數(shù) 不是對(duì)象 ,if語(yǔ)句塊不會(huì)執(zhí)行
}
下面通過(guò)兩種方式調(diào)用此函數(shù):
方式一:傳入對(duì)象
test({});//輸出結(jié)果:上例中的注釋
方式二:什么都不傳
test();//輸出結(jié)果:j的值:undefined
想不明白的是,在第二種方式中的輸出結(jié)果,為什么會(huì)是 undefined。我當(dāng)時(shí)猜的是:j的值:0
后來(lái),這本書(shū)上面說(shuō):
由于局部變量在整個(gè)函數(shù)體內(nèi)都是有聲明(或定義)的,這就意味著在整個(gè)函數(shù)體中都隱藏了同名的全局
變量。雖然 局部變量在整個(gè)函數(shù)體內(nèi)中都是有聲明(或定義)的,但是在執(zhí)行var語(yǔ)句之前,它是不會(huì)被初始化的。
這樣的話,上面的方式二調(diào)用的輸出結(jié)果,就比較好解釋了,由于變量j在整個(gè)函數(shù)中都有定義,而又由于傳入函數(shù)的參數(shù)為空,所以函數(shù)體中的if語(yǔ)句不會(huì)執(zhí)行,從而使得j的值為undefined.(這是我參照上面書(shū)上說(shuō)的那句話的理解)
下面的例子,更好的說(shuō)明:
var sssss = "全局變量";
function f(){
document.write("<br/>"+sssss);//輸出:undefined 而不是輸出"全局變量"
var sssss = "局部變量";
document.write("<br/>"+sssss);//輸出:局部變量
}
我的理解如下:
“聲明”變量,只是僅僅聲明,而“定義”變量,指聲明了,并且賦值了。
例如:
復(fù)制代碼 代碼如下:
var name;//只是聲明
var num = 11;//聲明,并且賦值,即定義了
var password = "yangjiang";//聲明,并且賦值,即定義了
下面是幾點(diǎn)總結(jié):
變量的作用域:全局的和局部的。(注意:如果嘗試讀取一個(gè)未聲明的變量的值,javascript會(huì)生成一個(gè)錯(cuò)誤)
第一點(diǎn):在都使用var關(guān)鍵字修飾變量的情況下,如果給一個(gè)局部變量或函數(shù)的參數(shù)聲明的名字與某個(gè)全局變量的名字相同,
那么就有效地隱藏了這個(gè)全局變量。
例如:
復(fù)制代碼 代碼如下:
var scope1 = "global";//var修飾
function checksScope(){
var scope1 = "local";//var修飾
document.write(scope1);
}checksScope();//local
第二點(diǎn):如果嘗試給一個(gè)未用 var 關(guān)鍵字聲明的變量,那么,隱式聲明的變量總是被創(chuàng)建為全局變量,即使
該變量只在一個(gè)函數(shù)體內(nèi)使用(只有該函數(shù)運(yùn)行了,才會(huì)發(fā)生作用),注意不支持函數(shù)嵌套的情形。
例如:
復(fù)制代碼 代碼如下:
scope2 = "globalAAAAA";//沒(méi)有使用var修飾(js會(huì)默認(rèn)將其聲明為全局變量)
function checkScopeA(){
scope2 = "localAAAAA";//沒(méi)有使用var修飾(js會(huì)默認(rèn)將其聲明為全局變量)
document.write("<br/>"+scope2);
myscope = "myLocalAAAAA";//沒(méi)有使用var修飾(js會(huì)默認(rèn)將其聲明為全局變量)
document.write(","+myscope);
}
checkScopeA();//localAAAAA,myLocalAAAAA *A
document.write("<br/>"+scope2);//localAAAAA *B
document.write("<br/>"+myscope);//myLocalAAAAA *C
如果將上面的例子中的 *A處的代碼注釋掉,
例如:
復(fù)制代碼 代碼如下:
scope2 = "globalAAAAA";//沒(méi)有使用var修飾(js會(huì)默認(rèn)將其聲明為全局變量)
function checkScopeA(){
scope2 = "localAAAAA";//沒(méi)有使用var修飾(js會(huì)默認(rèn)將其聲明為全局變量)
document.write("<br/>"+scope2);
myscope = "myLocalAAAAA";//沒(méi)有使用var修飾(js會(huì)默認(rèn)將其聲明為全局變量)
document.write(","+myscope);
}
//checkScopeA(); *A
document.write("<br/>"+scope2);//globalAAAAA *B
document.write("<br/>"+myscope);//發(fā)生錯(cuò)誤 *C
因?yàn)楹瘮?shù)checkScopeA沒(méi)有執(zhí)行,所以 *B處輸出為globalAAAAA;
因?yàn)楹瘮?shù)checkScopeA沒(méi)有執(zhí)行,所以變量myscope沒(méi)有聲明,如果嘗試讀取一個(gè)未聲明的變量,會(huì)發(fā)生錯(cuò)誤。
第三點(diǎn):
在javascript中,函數(shù)的定義是可以嵌套的。由于 每個(gè)函數(shù)都有它自己的局部作用域,所以有可能出現(xiàn)幾個(gè)局部作用域的嵌套層。
例如:
復(fù)制代碼 代碼如下:
var scope3 = "global scope"; //定義了一個(gè)全局變量
function checkScopeB(){
var scope3 = "local scope"; //定義了一個(gè)局部變量,覆蓋了全局變量scope3
function nested(){
var scope3 = "nested scope"; //在函數(shù)的函數(shù)的內(nèi)部,定義了一個(gè)局部變量
document.write("<br/>"+scope3); //nested scope
}
nested();
}
checkScopeB();//nested scope
第四點(diǎn):
在javascript中,沒(méi)有塊級(jí)作用域,函數(shù)中聲明的所有變量,無(wú)論是在哪里聲明的,在整個(gè)函數(shù)中它們都是有聲明的。
在javascript中,沒(méi)有塊級(jí)作用域,函數(shù)中定義的所有變量,無(wú)論是在哪里定義的,在整個(gè)函數(shù)中它們都是有定義的。
例如:
復(fù)制代碼 代碼如下:
function test(o){//根據(jù)以上的說(shuō)明:此函數(shù)中的i,j,k三個(gè)變量的作用域是相同的。
var i = 0; //變量 i 在整個(gè)函數(shù)中都有定義
if(typeof o == "object"){
var j = 0 ; //變量 j 在整個(gè)函數(shù)中都有定義,而不僅僅是在 if 語(yǔ)句塊
for(var k=0;k<10;k++){//變量 k 在整個(gè)函數(shù)中都有定義,而不僅僅是在 if 語(yǔ)句塊
document.write("<br/>k的值為:"+k);
}
document.write("<br/>for循環(huán)外k的值:"+k);//此時(shí)的 k 仍然被定義了,k=10
}
document.write("<br/>j的值:"+j); //變量 j 被聲明了,但可能沒(méi)有被初始化 因?yàn)榭赡芡瘮?shù)中 傳入的參數(shù) 不是對(duì)象 ,if語(yǔ)句塊不會(huì)執(zhí)行
}
下面通過(guò)兩種方式調(diào)用此函數(shù):
方式一:傳入對(duì)象
test({});//輸出結(jié)果:上例中的注釋
方式二:什么都不傳
test();//輸出結(jié)果:j的值:undefined
想不明白的是,在第二種方式中的輸出結(jié)果,為什么會(huì)是 undefined。我當(dāng)時(shí)猜的是:j的值:0
后來(lái),這本書(shū)上面說(shuō):
由于局部變量在整個(gè)函數(shù)體內(nèi)都是有聲明(或定義)的,這就意味著在整個(gè)函數(shù)體中都隱藏了同名的全局
變量。雖然 局部變量在整個(gè)函數(shù)體內(nèi)中都是有聲明(或定義)的,但是在執(zhí)行var語(yǔ)句之前,它是不會(huì)被初始化的。
這樣的話,上面的方式二調(diào)用的輸出結(jié)果,就比較好解釋了,由于變量j在整個(gè)函數(shù)中都有定義,而又由于傳入函數(shù)的參數(shù)為空,所以函數(shù)體中的if語(yǔ)句不會(huì)執(zhí)行,從而使得j的值為undefined.(這是我參照上面書(shū)上說(shuō)的那句話的理解)
下面的例子,更好的說(shuō)明:
復(fù)制代碼 代碼如下:
var sssss = "全局變量";
function f(){
document.write("<br/>"+sssss);//輸出:undefined 而不是輸出"全局變量"
var sssss = "局部變量";
document.write("<br/>"+sssss);//輸出:局部變量
}
您可能感興趣的文章:
- JavaScript的變量作用域深入理解
- 關(guān)于javascript 回調(diào)函數(shù)中變量作用域的討論
- 理解JavaScript變量作用域更輕松
- 關(guān)于JavaScript中var聲明變量作用域的推斷
- Javascript變量作用域詳解
- JavaScript 變量作用域及閉包
- javascript變量作用域使用中常見(jiàn)錯(cuò)誤總結(jié)
- 深入解析JavaScript中的變量作用域
- javascript 的變量、作用域和內(nèi)存問(wèn)題
- 簡(jiǎn)單談?wù)刯avascript中的變量、作用域和內(nèi)存問(wèn)題
- JavaScript變量作用域及內(nèi)存問(wèn)題實(shí)例分析
相關(guān)文章
javascript彈出一個(gè)層并增加一個(gè)覆蓋層
彈出一個(gè)層的js代碼,比較不錯(cuò)2008-10-10
javaScript中slice函數(shù)用法實(shí)例分析
這篇文章主要介紹了javaScript中slice函數(shù)用法,較為詳細(xì)的分析了javascript中slice函數(shù)的功能、定義及使用方法,需要的朋友可以參考下2015-06-06
Layui 導(dǎo)航默認(rèn)展開(kāi)和菜單欄選中高亮設(shè)置的方法
今天小編就為大家分享一篇Layui 導(dǎo)航默認(rèn)展開(kāi)和菜單欄選中高亮設(shè)置的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09
JS async 函數(shù)的含義和用法實(shí)例總結(jié)
這篇文章主要介紹了JS async 函數(shù)的含義和用法,結(jié)合實(shí)例形式總結(jié)分析了JS async 函數(shù)的基本功能、含義、使用方法及操作注意事項(xiàng),需要的朋友可以參考下2020-04-04
JS實(shí)現(xiàn)禁止高頻率連續(xù)點(diǎn)擊的方法【基于ES6語(yǔ)法】
這篇文章主要介紹了JS實(shí)現(xiàn)禁止高頻率連續(xù)點(diǎn)擊的方法,通過(guò)事件監(jiān)聽(tīng)結(jié)合定時(shí)器實(shí)現(xiàn)針對(duì)高頻率點(diǎn)擊的限制操作,該功能基于ES6語(yǔ)法實(shí)現(xiàn),需要的朋友可以參考下2017-04-04
JavaScript面向?qū)ο髮?shí)現(xiàn)貪吃蛇游戲
這篇文章主要為大家詳細(xì)介紹了JavaScript面向?qū)ο髮?shí)現(xiàn)貪吃蛇游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
JS實(shí)現(xiàn)圖片幻燈片效果代碼實(shí)例
這篇文章主要介紹了JS實(shí)現(xiàn)圖片幻燈片效果代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
基于JS實(shí)現(xiàn)頁(yè)面懸浮框的實(shí)例代碼
這篇文章主要介紹了基于JS實(shí)現(xiàn)頁(yè)面懸浮框的實(shí)例代碼,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12

