js变量作用域及可访问性的探讨


Posted in Javascript onNovember 23, 2006

每一种语言都有变量的概念,变量是用来存储信息的一个元素。比如下面这个函数: 

 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;  
  }  
}
 
   Student类有三个变量,分别为name(名字),age(年龄),from(籍贯),这三个变量构成了描述一个对象的信息。当然,这里还有一个方法用来返回Student的信息。
   但是,我们是不是定义了一个变量,它就能一直存在着,并且还有可能在任何地方都能被访问和使用直到其被销毁?仔细想想,上面的需求是比较过分的,因为某些变量在某个功能实现后就不再利用了,但如果这个变量还存在的话,就占用了系统资源了,俗语曰:“站着茅坑不拉#$%”。
   于是我们对变量的及时和按需求地销毁有一个探讨的话题了。
   好,切入正题吧,就本人所接触过的来讲,js中支持如下几种类型的变量,分别为:局部变量、类变量、私有变量、实例变量、静态变量和全局变量。接下来我们就一一探讨研究下。

局部变量:

局部变量一般指在{}范围内有效变量,也就是语句块内有效的变量,如: 

 

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>"); 
   该代码执行后输出的结果为:“index is :undefined” 和 “result is :0”,我们可以看到希望输出的index变量的值为undefined,也就是未定义。因此我们可以发现,index变量在if语句块结束后即被销毁了。那么“sum”变量呢?这个变量在foo()函数段执行完毕后被销毁了,如果您去掉我注释的那条语句,再执行,您将会发现系统将报错。值得注意的是,如果我把上面的foo()函数改成如下: 

 

function foo(flag)  
 {  
  var sum = 0;  
  for(var index=0;index<10;index++)  
  {  
   sum +=index;  
  }  
  document.write("index is :"+index+"<br>");  
  return sum;  
} 

   您将可以看见可以输出index值("index is :10"),这个是js和其他语言的不同地方,因为index是在for循环的{}外面定义的,因此其作用范围在foo()函数使用完毕后才销毁。

  类变量:
   类变量,实际上就是类的一个属性或字段或一个方法,该变量在该类的一个实例对象被销毁后自动销毁,比如我们开始时举的Student类。这个我们不多讨论,大家可以自己试一下。

私有变量:
   私有变量,值得是某个类自己内部是用的一个属性,外部无法调用,其定义是用 var 来声明的。注意如果不用var 来声明,该变量将是全局变量(我们下面将会讨论),如: 

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

   这里,我们分别定义了一个origName和FormatIt()两个私有变量(按面向对象的解释,应该用类的属性来称呼)。
   我们把这种情况下的方法也成为变量,因为该情况下的变量是个function类型的变量,而function也属于Object类的继承类。在这种情形下,如果我们定义了 var zfp = new Student("3zfp",100,"ShenZhen")。但无法通过zfp.origName和zfp.FormatIt()方式来访问这两个变量的。

注意以下几点:

1、私有变量是不能用this来指示的。
2、私有方法类型的变量的调用必须是在该方法声明后。如我们将Student类改造如下:

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"); 
代码执行后,将会报"找不到对象"的错误.意思是FormatName()未定义。

3、私有方法无法访问this指示的变量(公开变量),如下:

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")); 
执行代码后,系统将会提示 “this.basicInfo为空或不是对象”的错误。
基本结论是,私有方法只能访问私有属性,私有属性在声明并赋值后可以在类的任何地方访问,

实例变量:
实例变量即某个实例对象所拥有的变量。如:

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>");  
执行该代码后,我们将可以看到如下结果:  
basicA's generalInfo is : is 3zfp owned object  
basicB's generalInfo is : undefined 
静态变量:

静态变量即为某个类所拥有的属性,通过 类名+"."+静态变量名 的方式访问该属性。如下可以做清晰的解释:

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>"); 

执行以上代码,将会得到如下结果:
undefined
is 3zfp owned object
info is changed

注意以下几点:
1、以 类名+"."+静态变量名 的方式来声明一个静态变量
2、静态变量并不属于类的某个实例对象所独有的属性,为对象的共享.
3、能以实例对象名+"."+静态变量名来访问。

全局变量:
全局变量即整个系统运行期间有效访问控制的变量,通常是在一个js代码开头定义,如:

var copyright = "3zfp owned";  
var foo =function()  
{  
 window.alert(copyright);  
} 
注意以下几点:
1、如果一个变量不用var 来声明,则其被视为全局变量。如:
var copyright = "3zfp owned";
var foo =function(fooInfo)
{
 _foo = fooInfo;
document.write(copyright+"<br>");
}
new foo("foo test");
document.write(_foo+"<br>");
执行代码,将得到如下结果:
3zfp owned
foo test
但是,这个又有一个注意的地方,function是编译期对象,也就是说_foo这个全局变量要在foo对象被实例化后才能被初始化,也就是说如果将
new foo();
document.write(_foo+"<br>");
对调成
document.write(_foo+"<br>");
new foo();
系统将提示 "_foo 未定义"。 
2、如果定义了一个和全局变量同名的局部变量属性,如下:
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>"); 
执行代码,将得到如下结果:
3zfp owned
foo test

原因是由于function 是在编译期间完成变量的定义,也就是foo内部的copyright的定义是在编译期间完成的,其作用域只在foo对象内有效,而与外部定义的全局变量copyright无关。

Javascript 相关文章推荐
彪哥1.1(智能表格)提供下载
Sep 07 Javascript
javascript smipleChart 简单图标类
Jan 12 Javascript
纯javascript实现自动发送邮件
Oct 21 Javascript
Webpack 实现 Node.js 代码热替换
Oct 22 Javascript
Boostrap模态窗口的学习小结
Mar 28 Javascript
JS实现自动轮播图效果(自适应屏幕宽度+手机触屏滑动)
Jun 19 Javascript
深入浅出es6模板字符串
Aug 26 Javascript
用p5.js制作烟花特效的示例代码
Mar 21 Javascript
Vue.js 实现地址管理页面思路详解(地址添加、编辑、删除和设置默认地址)
Dec 11 Javascript
如何通过javaScript去除字符串两端的空白字符
Feb 06 Javascript
用vue 实现手机触屏滑动功能
May 28 Javascript
Vue3配置axios跨域实现过程解析
Nov 25 Vue.js
bcastr2.0 通用的图片浏览器
Nov 22 #Javascript
一种JavaScript的设计模式
Nov 22 #Javascript
表单内同名元素的控制
Nov 22 #Javascript
document.all与WEB标准
May 13 #Javascript
云网广告中的代码,提示出错,大家找找
Nov 21 #Javascript
在视频前插入广告
Nov 20 #Javascript
使两个iframe的高度与内容自适应,且相等
Nov 20 #Javascript
You might like
PHP下通过exec获得计算机的唯一标识[CPU,网卡 MAC地址]
2011/06/09 PHP
深入解析PHP的引用计数机制
2013/06/14 PHP
PHP防止刷新重复提交页面的示例代码
2015/11/11 PHP
Smarty分页实现方法完整实例
2016/05/11 PHP
CodeIgniter 完美解决URL含有中文字符串
2016/05/13 PHP
ThinkPHP 3.2.2实现事务操作的方法
2017/05/05 PHP
Laravel框架中自定义模板指令总结
2017/12/17 PHP
win10 apache配置虚拟主机后localhost无法使用的解决方法
2018/01/27 PHP
js实现回放拖拽轨迹从过程上进行分析
2014/06/26 Javascript
微信浏览器内置JavaScript对象WeixinJSBridge使用实例
2015/05/25 Javascript
学习JavaScript设计模式之享元模式
2016/01/18 Javascript
Javascript 创建类并动态添加属性及方法的简单实现
2016/10/20 Javascript
canvas实现流星雨的背景效果
2017/01/13 Javascript
在Js页面通过POST传递参数跳转到新页面详解
2017/08/25 Javascript
详解vue-cli 本地开发mock数据使用方法
2018/05/29 Javascript
js如何找出字符串中的最长回文串
2018/06/04 Javascript
javascript设计模式之迭代器模式
2020/01/30 Javascript
[34:10]Secret vs VG 2019国际邀请赛淘汰赛 败者组 BO3 第二场 8.24
2019/09/10 DOTA
python通过BF算法实现关键词匹配的方法
2015/03/13 Python
极简的Python入门指引
2015/04/01 Python
Python内置模块ConfigParser实现配置读写功能的方法
2018/02/12 Python
python多进程提取处理大量文本的关键词方法
2018/06/05 Python
django 自定义过滤器的实现
2019/02/26 Python
pyqt5之将textBrowser的内容写入txt文档的方法
2019/06/21 Python
pytorch加载自定义网络权重的实现
2020/01/07 Python
使用javascript和HTML5 Canvas画的四渐变色播放按钮效果
2014/04/10 HTML / CSS
你的自行车健身专家:FaFit24
2016/11/16 全球购物
会计系毕业个人自荐信格式
2013/09/23 职场文书
高三毕业典礼演讲稿
2014/05/13 职场文书
文艺演出策划方案
2014/06/07 职场文书
期末考试复习计划
2015/01/19 职场文书
西双版纳导游词
2015/02/03 职场文书
3.15消费者权益日活动总结
2015/02/09 职场文书
重阳节活动主持词
2015/07/04 职场文书
PHP中->和=>的意思
2021/03/31 PHP
Python探索生命起源 matplotlib细胞自动机动画演示
2022/04/21 Python