js變量作用域及可訪問(wèn)性的探討
更新時(shí)間:2006年11月23日 00:00:00 作者:
每一種語(yǔ)言都有變量的概念,變量是用來(lái)存儲(chǔ)信息的一個(gè)元素。比如下面這個(gè)函數(shù):
Student類有三個(gè)變量,分別為name(名字),age(年齡),from(籍貫),這三個(gè)變量構(gòu)成了描述一個(gè)對(duì)象的信息。當(dāng)然,這里還有一個(gè)方法用來(lái)返回Student的信息。
但是,我們是不是定義了一個(gè)變量,它就能一直存在著,并且還有可能在任何地方都能被訪問(wèn)和使用直到其被銷毀?仔細(xì)想想,上面的需求是比較過(guò)分的,因?yàn)槟承┳兞吭谀硞€(gè)功能實(shí)現(xiàn)后就不再利用了,但如果這個(gè)變量還存在的話,就占用了系統(tǒng)資源了,俗語(yǔ)曰:“站著茅坑不拉#$%”。
于是我們對(duì)變量的及時(shí)和按需求地銷毀有一個(gè)探討的話題了。
好,切入正題吧,就本人所接觸過(guò)的來(lái)講,js中支持如下幾種類型的變量,分別為:局部變量、類變量、私有變量、實(shí)例變量、靜態(tài)變量和全局變量。接下來(lái)我們就一一探討研究下。
局部變量:
局部變量一般指在{}范圍內(nèi)有效變量,也就是語(yǔ)句塊內(nèi)有效的變量,如:
您將可以看見(jiàn)可以輸出index值("index is :10"),這個(gè)是js和其他語(yǔ)言的不同地方,因?yàn)閕ndex是在for循環(huán)的{}外面定義的,因此其作用范圍在foo()函數(shù)使用完畢后才銷毀。
類變量:
類變量,實(shí)際上就是類的一個(gè)屬性或字段或一個(gè)方法,該變量在該類的一個(gè)實(shí)例對(duì)象被銷毀后自動(dòng)銷毀,比如我們開始時(shí)舉的Student類。這個(gè)我們不多討論,大家可以自己試一下。
私有變量:
私有變量,值得是某個(gè)類自己內(nèi)部是用的一個(gè)屬性,外部無(wú)法調(diào)用,其定義是用 var 來(lái)聲明的。注意如果不用var 來(lái)聲明,該變量將是全局變量(我們下面將會(huì)討論),如:
這里,我們分別定義了一個(gè)origName和FormatIt()兩個(gè)私有變量(按面向?qū)ο蟮慕忉?,?yīng)該用類的屬性來(lái)稱呼)。
我們把這種情況下的方法也成為變量,因?yàn)樵撉闆r下的變量是個(gè)function類型的變量,而function也屬于Object類的繼承類。在這種情形下,如果我們定義了 var zfp = new Student("3zfp",100,"ShenZhen")。但無(wú)法通過(guò)zfp.origName和zfp.FormatIt()方式來(lái)訪問(wèn)這兩個(gè)變量的。
注意以下幾點(diǎn):
1、私有變量是不能用this來(lái)指示的。
2、私有方法類型的變量的調(diào)用必須是在該方法聲明后。如我們將Student類改造如下:
3、私有方法無(wú)法訪問(wèn)this指示的變量(公開變量),如下:
基本結(jié)論是,私有方法只能訪問(wèn)私有屬性,私有屬性在聲明并賦值后可以在類的任何地方訪問(wèn),
實(shí)例變量:
實(shí)例變量即某個(gè)實(shí)例對(duì)象所擁有的變量。如:
靜態(tài)變量即為某個(gè)類所擁有的屬性,通過(guò) 類名+"."+靜態(tài)變量名 的方式訪問(wèn)該屬性。如下可以做清晰的解釋:
執(zhí)行以上代碼,將會(huì)得到如下結(jié)果:
undefined
is 3zfp owned object
info is changed
注意以下幾點(diǎn):
1、以 類名+"."+靜態(tài)變量名 的方式來(lái)聲明一個(gè)靜態(tài)變量
2、靜態(tài)變量并不屬于類的某個(gè)實(shí)例對(duì)象所獨(dú)有的屬性,為對(duì)象的共享.
3、能以實(shí)例對(duì)象名+"."+靜態(tài)變量名來(lái)訪問(wèn)。
全局變量:
全局變量即整個(gè)系統(tǒng)運(yùn)行期間有效訪問(wèn)控制的變量,通常是在一個(gè)js代碼開頭定義,如:
1、如果一個(gè)變量不用var 來(lái)聲明,則其被視為全局變量。如:
var copyright = "3zfp owned";
var foo =function(fooInfo)
{
_foo = fooInfo;
document.write(copyright+"<br>");
}
new foo("foo test");
document.write(_foo+"<br>");
執(zhí)行代碼,將得到如下結(jié)果:
3zfp owned
foo test
但是,這個(gè)又有一個(gè)注意的地方,function是編譯期對(duì)象,也就是說(shuō)_foo這個(gè)全局變量要在foo對(duì)象被實(shí)例化后才能被初始化,也就是說(shuō)如果將
new foo();
document.write(_foo+"<br>");
對(duì)調(diào)成
document.write(_foo+"<br>");
new foo();
系統(tǒng)將提示 "_foo 未定義"。
2、如果定義了一個(gè)和全局變量同名的局部變量屬性,如下:
3zfp owned
foo test
原因是由于function 是在編譯期間完成變量的定義,也就是foo內(nèi)部的copyright的定義是在編譯期間完成的,其作用域只在foo對(duì)象內(nèi)有效,而與外部定義的全局變量copyright無(wú)關(guān)。
復(fù)制代碼 代碼如下:
function Student(name,age,from)
{
this.name = name;
this.age = age;
this.from = from;
this.ToString = function()
{
return "my information is name: "+this.name+",age : "+this.age+", from :" +this.from;
}
}
{
this.name = name;
this.age = age;
this.from = from;
this.ToString = function()
{
return "my information is name: "+this.name+",age : "+this.age+", from :" +this.from;
}
}
Student類有三個(gè)變量,分別為name(名字),age(年齡),from(籍貫),這三個(gè)變量構(gòu)成了描述一個(gè)對(duì)象的信息。當(dāng)然,這里還有一個(gè)方法用來(lái)返回Student的信息。
但是,我們是不是定義了一個(gè)變量,它就能一直存在著,并且還有可能在任何地方都能被訪問(wèn)和使用直到其被銷毀?仔細(xì)想想,上面的需求是比較過(guò)分的,因?yàn)槟承┳兞吭谀硞€(gè)功能實(shí)現(xiàn)后就不再利用了,但如果這個(gè)變量還存在的話,就占用了系統(tǒng)資源了,俗語(yǔ)曰:“站著茅坑不拉#$%”。
于是我們對(duì)變量的及時(shí)和按需求地銷毀有一個(gè)探討的話題了。
好,切入正題吧,就本人所接觸過(guò)的來(lái)講,js中支持如下幾種類型的變量,分別為:局部變量、類變量、私有變量、實(shí)例變量、靜態(tài)變量和全局變量。接下來(lái)我們就一一探討研究下。
局部變量:
局部變量一般指在{}范圍內(nèi)有效變量,也就是語(yǔ)句塊內(nèi)有效的變量,如:
復(fù)制代碼 代碼如下:
function foo(flag)
{
var sum = 0;
if(flag == true)
{
var index;
for(index=0;index<10;index++)
{
sum +=index;
}
}
document.write("index is :"+index+"<br>");
return sum;
}
//document.write("sum is :" +sum+"<br>");
document.write("result is :"+foo(true)+"<br>");
該代碼執(zhí)行后輸出的結(jié)果為:“index is :undefined” 和 “result is :0”,我們可以看到希望輸出的index變量的值為undefined,也就是未定義。因此我們可以發(fā)現(xiàn),index變量在if語(yǔ)句塊結(jié)束后即被銷毀了。那么“sum”變量呢?這個(gè)變量在foo()函數(shù)段執(zhí)行完畢后被銷毀了,如果您去掉我注釋的那條語(yǔ)句,再執(zhí)行,您將會(huì)發(fā)現(xiàn)系統(tǒng)將報(bào)錯(cuò)。值得注意的是,如果我把上面的foo()函數(shù)改成如下: {
var sum = 0;
if(flag == true)
{
var index;
for(index=0;index<10;index++)
{
sum +=index;
}
}
document.write("index is :"+index+"<br>");
return sum;
}
//document.write("sum is :" +sum+"<br>");
document.write("result is :"+foo(true)+"<br>");
復(fù)制代碼 代碼如下:
function foo(flag)
{
var sum = 0;
for(var index=0;index<10;index++)
{
sum +=index;
}
document.write("index is :"+index+"<br>");
return sum;
}
{
var sum = 0;
for(var index=0;index<10;index++)
{
sum +=index;
}
document.write("index is :"+index+"<br>");
return sum;
}
您將可以看見(jiàn)可以輸出index值("index is :10"),這個(gè)是js和其他語(yǔ)言的不同地方,因?yàn)閕ndex是在for循環(huán)的{}外面定義的,因此其作用范圍在foo()函數(shù)使用完畢后才銷毀。
類變量:
類變量,實(shí)際上就是類的一個(gè)屬性或字段或一個(gè)方法,該變量在該類的一個(gè)實(shí)例對(duì)象被銷毀后自動(dòng)銷毀,比如我們開始時(shí)舉的Student類。這個(gè)我們不多討論,大家可以自己試一下。
私有變量:
私有變量,值得是某個(gè)類自己內(nèi)部是用的一個(gè)屬性,外部無(wú)法調(diào)用,其定義是用 var 來(lái)聲明的。注意如果不用var 來(lái)聲明,該變量將是全局變量(我們下面將會(huì)討論),如:
復(fù)制代碼 代碼如下:
function Student(name,age,from)
{
this.name = FormatIt(name);
this.age = age;
this.from = from;
var origName = name;
var FormatIt = function(name)
{
return name.substr(0,5);
}
this.ToString = function()
{
return "my information is name: "+origName+",age : "+this.age+", from :" +this.from;
}
}
{
this.name = FormatIt(name);
this.age = age;
this.from = from;
var origName = name;
var FormatIt = function(name)
{
return name.substr(0,5);
}
this.ToString = function()
{
return "my information is name: "+origName+",age : "+this.age+", from :" +this.from;
}
}
這里,我們分別定義了一個(gè)origName和FormatIt()兩個(gè)私有變量(按面向?qū)ο蟮慕忉?,?yīng)該用類的屬性來(lái)稱呼)。
我們把這種情況下的方法也成為變量,因?yàn)樵撉闆r下的變量是個(gè)function類型的變量,而function也屬于Object類的繼承類。在這種情形下,如果我們定義了 var zfp = new Student("3zfp",100,"ShenZhen")。但無(wú)法通過(guò)zfp.origName和zfp.FormatIt()方式來(lái)訪問(wèn)這兩個(gè)變量的。
注意以下幾點(diǎn):
1、私有變量是不能用this來(lái)指示的。
2、私有方法類型的變量的調(diào)用必須是在該方法聲明后。如我們將Student類改造如下:
復(fù)制代碼 代碼如下:
function Student(name,age,from)
{
var origName = name;
this.name = FormatName(name);
this.age = age;
this.from = from;
var FormatName = function(name)
{
return name+".china";
}
this.ToString = function()
{
return "my information is name: "+origName+",age : "+this.age+", from :" +this.from;
}
}
var zfp = new Student("3zfp",100,"ShenZhen");
代碼執(zhí)行后,將會(huì)報(bào)"找不到對(duì)象"的錯(cuò)誤.意思是FormatName()未定義。 {
var origName = name;
this.name = FormatName(name);
this.age = age;
this.from = from;
var FormatName = function(name)
{
return name+".china";
}
this.ToString = function()
{
return "my information is name: "+origName+",age : "+this.age+", from :" +this.from;
}
}
var zfp = new Student("3zfp",100,"ShenZhen");
3、私有方法無(wú)法訪問(wèn)this指示的變量(公開變量),如下:
復(fù)制代碼 代碼如下:
function Student(basicinfo)
{
this.basicInfo = basicinfo;
var FormatInfo = function()
{
this.basicInfo.name = this.basicInfo.name+".china";
}
FormatInfo();
}
function BasicInfo(name,age,from)
{
this.name = name;
this.age = age;
this.from = from;
}
var zfp = new Student(new BasicInfo("3zfp",100,"ShenZhen"));
執(zhí)行代碼后,系統(tǒng)將會(huì)提示 “this.basicInfo為空或不是對(duì)象”的錯(cuò)誤。 {
this.basicInfo = basicinfo;
var FormatInfo = function()
{
this.basicInfo.name = this.basicInfo.name+".china";
}
FormatInfo();
}
function BasicInfo(name,age,from)
{
this.name = name;
this.age = age;
this.from = from;
}
var zfp = new Student(new BasicInfo("3zfp",100,"ShenZhen"));
基本結(jié)論是,私有方法只能訪問(wèn)私有屬性,私有屬性在聲明并賦值后可以在類的任何地方訪問(wèn),
實(shí)例變量:
實(shí)例變量即某個(gè)實(shí)例對(duì)象所擁有的變量。如:
復(fù)制代碼 代碼如下:
function BasicInfo(name,age,from)
{
this.name = name;
this.age = age;
this.from = from;
}
var basicA = new BasicInfo("3zfp",100,"ShenZhen");
basicA.generalInfo = "is 3zfp owned object";
document.write("basicA's generalInfo is : "+ basicA.generalInfo+"<br>");
var basicB = new BasicInfo("zfp",100,"ShenZhen");
document.write("basicB's generalInfo is : "+ basicB.generalInfo+"<br>");
執(zhí)行該代碼后,我們將可以看到如下結(jié)果:
basicA's generalInfo is : is 3zfp owned object
basicB's generalInfo is : undefined
靜態(tài)變量: {
this.name = name;
this.age = age;
this.from = from;
}
var basicA = new BasicInfo("3zfp",100,"ShenZhen");
basicA.generalInfo = "is 3zfp owned object";
document.write("basicA's generalInfo is : "+ basicA.generalInfo+"<br>");
var basicB = new BasicInfo("zfp",100,"ShenZhen");
document.write("basicB's generalInfo is : "+ basicB.generalInfo+"<br>");
執(zhí)行該代碼后,我們將可以看到如下結(jié)果:
basicA's generalInfo is : is 3zfp owned object
basicB's generalInfo is : undefined
靜態(tài)變量即為某個(gè)類所擁有的屬性,通過(guò) 類名+"."+靜態(tài)變量名 的方式訪問(wèn)該屬性。如下可以做清晰的解釋:
復(fù)制代碼 代碼如下:
function BasicInfo(name,age,from)
{
this.name = name;
this.age = age;
this.from = from;
}
BasicInfo.generalInfo = "is 3zfp owned object";
var basic = new BasicInfo("zfp",100,"ShenZhen");
document.write(basic.generalInfo+"<br>");
document.write(BasicInfo.generalInfo+"<br>");
BasicInfo.generalInfo = "info is changed";
document.write(BasicInfo.generalInfo+"<br>");
{
this.name = name;
this.age = age;
this.from = from;
}
BasicInfo.generalInfo = "is 3zfp owned object";
var basic = new BasicInfo("zfp",100,"ShenZhen");
document.write(basic.generalInfo+"<br>");
document.write(BasicInfo.generalInfo+"<br>");
BasicInfo.generalInfo = "info is changed";
document.write(BasicInfo.generalInfo+"<br>");
執(zhí)行以上代碼,將會(huì)得到如下結(jié)果:
undefined
is 3zfp owned object
info is changed
注意以下幾點(diǎn):
1、以 類名+"."+靜態(tài)變量名 的方式來(lái)聲明一個(gè)靜態(tài)變量
2、靜態(tài)變量并不屬于類的某個(gè)實(shí)例對(duì)象所獨(dú)有的屬性,為對(duì)象的共享.
3、能以實(shí)例對(duì)象名+"."+靜態(tài)變量名來(lái)訪問(wèn)。
全局變量:
全局變量即整個(gè)系統(tǒng)運(yùn)行期間有效訪問(wèn)控制的變量,通常是在一個(gè)js代碼開頭定義,如:
復(fù)制代碼 代碼如下:
var copyright = "3zfp owned";
var foo =function()
{
window.alert(copyright);
}
注意以下幾點(diǎn): var foo =function()
{
window.alert(copyright);
}
1、如果一個(gè)變量不用var 來(lái)聲明,則其被視為全局變量。如:
var copyright = "3zfp owned";
var foo =function(fooInfo)
{
_foo = fooInfo;
document.write(copyright+"<br>");
}
new foo("foo test");
document.write(_foo+"<br>");
執(zhí)行代碼,將得到如下結(jié)果:
3zfp owned
foo test
但是,這個(gè)又有一個(gè)注意的地方,function是編譯期對(duì)象,也就是說(shuō)_foo這個(gè)全局變量要在foo對(duì)象被實(shí)例化后才能被初始化,也就是說(shuō)如果將
new foo();
document.write(_foo+"<br>");
對(duì)調(diào)成
document.write(_foo+"<br>");
new foo();
系統(tǒng)將提示 "_foo 未定義"。
2、如果定義了一個(gè)和全局變量同名的局部變量屬性,如下:
復(fù)制代碼 代碼如下:
var copyright = "3zfp owned";
var foo =function(fooInfo)
{
var copyright = fooInfo; //同名變量
this.showInfo = function()
{
document.write(copyright+"<br>");
}
}
new foo("foo test").showInfo();
document.write(copyright+"<br>");
執(zhí)行代碼,將得到如下結(jié)果: var foo =function(fooInfo)
{
var copyright = fooInfo; //同名變量
this.showInfo = function()
{
document.write(copyright+"<br>");
}
}
new foo("foo test").showInfo();
document.write(copyright+"<br>");
3zfp owned
foo test
原因是由于function 是在編譯期間完成變量的定義,也就是foo內(nèi)部的copyright的定義是在編譯期間完成的,其作用域只在foo對(duì)象內(nèi)有效,而與外部定義的全局變量copyright無(wú)關(guān)。
相關(guān)文章
Bootstrap彈出框(modal)垂直居中的問(wèn)題及解決方案詳解
這篇文章主要介紹了Bootstrap彈出框(modal)垂直居中的問(wèn)題及解決方案詳解的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06ES6?Promise.all的使用方法以及其細(xì)節(jié)詳解
Promise對(duì)象用于表示一個(gè)異步操作的最終完成(或失敗)及其結(jié)果值,下面這篇文章主要給大家介紹了關(guān)于ES6?Promise.all的使用方法以及其細(xì)節(jié)的相關(guān)資料,需要的朋友可以參考下2022-07-07JS中使用cavas截圖網(wǎng)頁(yè)并解決跨域及模糊問(wèn)題
這篇文章主要介紹了JS中使用cavas截取網(wǎng)頁(yè)并解決跨域以及模糊問(wèn)題 ,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-11-11其實(shí)你可以少寫點(diǎn)if else與switch(推薦)
switch case與if else的區(qū)別:switch case會(huì)生成一個(gè)跳轉(zhuǎn)表來(lái)指示實(shí)際的case分支的地址,而if...else卻需要遍歷條件分支直到命中條件,下面這篇文章主要給大家介紹了關(guān)于if else與switch在使用中的一些技巧,需要的朋友可以參考下2019-01-01左右懸浮可分組的網(wǎng)站QQ在線客服代碼(可謂經(jīng)典)
QQ在線客服在每一個(gè)web開發(fā)人員的記憶里都是一個(gè)經(jīng)典,既然是經(jīng)典,也就是必不可少,那就應(yīng)該很好的呈現(xiàn)出來(lái),本文整理了一些左右懸浮可分組的網(wǎng)站QQ在線客服代碼,需要的朋友可以了解下2012-12-12javascript實(shí)現(xiàn)禁止復(fù)制網(wǎng)頁(yè)內(nèi)容
這篇文章主要介紹了javascript實(shí)現(xiàn)禁止復(fù)制網(wǎng)頁(yè)內(nèi)容,需要的朋友可以參考下2014-12-12