不错的JS中变量相关的细节分析


Posted in Javascript onAugust 13, 2007

这里讨论一下我对Javascript中变量相关细节的认识,有不当之处欢迎来批。

一、变量的类型

Javascript和Java、C这些语言不同,它是一种无类型、弱检测的语言。它对变量的定义并不需要声明变量类型,我们只要通过赋值的形式,可以将各种类型的数据赋值给同一个变量。例如:

i=100;//Number类型
i="variable";//String类型
i={x:4};//Object类型
i=[1,2,3];//Array类型

JS的这种特性虽然让我们的编码更加灵活,但也带来了一个弊端,不利于Debug,编译器的弱检测让我们维护冗长的代码时相当痛苦。

二、变量的声明

JS中变量申明分显式申明和隐式申明。

var i=100;//显式申明
i=100;//隐式申明

在函数中使用var关键字进行显式申明的变量是做为局部变量,而没有用var关键字,使用直接赋值方式声明的是全局变量。

 

当我们使用访问一个没有声明的变量时,JS会报错。而当我们给一个没有声明的变量赋值时,JS不会报错,相反它会认为我们是要隐式申明一个全局变量,这一点一定要注意。

三、全局变量和局部变量

当JS解析器执行时,首先就会在执行环境里构建一个全局对象,我们定义的全局属性就是做为该对象的属性读取,在顶层代码中我们使用this关键字和window对象都可以访问到它。而函数体中的局部变量只在函数执行时生成的调用对象中存在,函数执行完毕时局部变量即刻销毁。因此在程序设计中我们需要考虑如何合理声明变量,这样既减小了不必要的内存开销,同时能很大程度地避免变量重复定义而覆盖先前定义的变量所造成的Debug麻烦。

四、变量作用域

任何程序语言中变量的作用域都是一个很关键的细节。JS中变量的作用域相对与JAVA、C这类语言显得更自由,一个很大的特征就是JS变量没有块级作用域,函数中的变量在整个函数都中有效,运行下面代码:

<SCRIPT LANGUAGE="JavaScript" type="text/javascript">
//定义一个输出函数
function outPut(s){
document.writeln(s)
}
//全局变量
var i=0;
//定义外部函数
function outer(){
//访问全局变量
outPut(i); // 0
//定义一个类部函数
function inner(){
//定义局部变量
var i = 1;
// i=1; 如果用隐式申明 那么就覆盖了全局变量i
outPut(i); //1
}
inner();
outPut(i); //0
}
outer();
</SCRIPT>

输出结果为0 1 0,从上面就可以证明JS如果用var在函数体中声明变量,那么此变量在且只在该函数体内有效,函数运行结束时,本地变量即可销毁了。

由于上面的这个JS特性,还有一个关键的问题需要注意。此前一直使用ActionScript,虽然它和JS都是基于ECMA标准的,但在这里还是略有不同的。例如下面代码:

<SCRIPT LANGUAGE="JavaScript" type="text/javascript">
//定义一个输出函数
function outPut(s){
document.writeln(s)
}
//全局变量
var i=0;
//定义外部函数
function outer(){
//访问全局变量
outPut(i); // 0
//定义一个类部函数
function inner(){
outPut(i); //undefiend
var i=1;
outPut(i); //1
}
inner();
outPut(i); //0
}
outer();
</SCRIPT>

你可能认为输出结果是0 0 1 0,事实上在AS中确实是这样的,而在JS中的输入却是0 undefined 1 0,为何会这样了?刚才我们说到了JS函数体中声明的本地变量在整个函数中都有效,因此在上面代码中var i = 1 ;在inner函数中都有效,实际上显式声明的变量i是在预编译时就已经编译到调用对象中了,不同于隐式声明变量在解释时才被定义为全局变量,只是在调用outPut(i)时,还没有将它初始化变量,此时的本地变量i是未赋值变量,而不是未定义变量,因此输出了undefined。上面的代码等效于下面代码:

function inner(){
var i; //定义但不赋值
outPut(i); //undefiend
i=1;
outPut(i); //1
}

为了避免上面的这类问题,因此在函数开始位置集中做函数声明是一个极力推荐的做法。

五、基本类型和引用类型

JS不同于JAVA、C这些语言,在变量申明时并不需要声明变量的存储空间。变量中所存储的数据可以分为两类:基本类型和引用类型。其中数值、布尔值、null和undefined属于基本类型,对象、数组和函数属于引用类型。

基本类型在内存中具有固定的内存大小。例如:数值型在内存中占有八个字节,布尔值只占有一个字节。对于引用型数据,他们可以具有任意长度,因此他们的内存大小是不定的,因此变量中存储的实际上是对此数据的引用,通常是内存地址或者指针,通过它们我们可以找到这个数据。

引用类型和基本类型在使用行为上也有不同之处:

<SCRIPT LANGUAGE="JavaScript" type="text/javascript">
//定义一个输出函数
function outPut(s){
document.writeln(s)
}
var a = 3;
var b = a;
outPut(b);
//3
a = 4;
outPut(a);
//4
outPut(b);
//3
</SCRIPT>

对基本类型b进行赋值时,实际上是又开辟了一块内存空间,因此改变变量a的值对变量b没有任何影响。

<SCRIPT LANGUAGE="JavaScript" type="text/javascript">
//定义一个输出函数
function outPut(s){
document.writeln(s)
}
var a_array = [1,2,3];
var b_array = a_array;
outPut(b_array); //1,2,3 
a_array[3] = 4;
outPut(b_array);//1,2,3,4
</SCRIPT>

上面是对引用类型的变量赋值,实际上他们传递的是对内存地址的引用,因此对a_array和b_array的存取,实际上都是操作的同一块内存区域。如果希望重新分配内存空间存储引用型变量,那么我就需要使用克隆方法或者自定义方法来复制引用变量的数据。

Javascript 相关文章推荐
jquery中对表单的基本操作代码
Jul 29 Javascript
用JS控制回车事件的代码
Feb 20 Javascript
ASP.NET jQuery 实例11 通过使用jQuery validation插件简单实现用户登录页面验证功能
Feb 03 Javascript
js取消单选按钮选中并判断对象是否为空
Nov 14 Javascript
图片放大镜jquery.jqzoom.js使用实例附放大镜图标
Jun 19 Javascript
Javascript中封装window.open解决不兼容问题
Sep 28 Javascript
基于jquery ui的alert,confirm方案(支持换肤)
Apr 03 Javascript
jQuery地图map悬停显示省市代码分享
Aug 20 Javascript
JS点击图片弹出文件选择框并覆盖原图功能的实现代码
Aug 25 Javascript
浅谈v-for 和 v-if 并用时筛选条件方法
Nov 07 Javascript
vue 修改 data 数据问题并实时显示操作
Sep 07 Javascript
vue element实现表格合并行数据
Nov 30 Vue.js
javascript-TreeView父子联动效果保持节点状态一致
Aug 12 #Javascript
TopList标签和JavaScript结合两例
Aug 12 #Javascript
Javascript-Mozilla和IE中的一个函数直接量的问题分析
Aug 12 #Javascript
IE和Mozilla的兼容性汇总event
Aug 12 #Javascript
收藏Javascript中常用的55个经典技巧
Aug 12 #Javascript
JavaScript-世界上误解最深的语言分析
Aug 12 #Javascript
用javascript实现兼容IE7的类库 IE7_0_9.zip提供下载
Aug 08 #Javascript
You might like
php $_SERVER[&quot;REQUEST_URI&quot;]获取值的通用解决方法
2010/06/21 PHP
PHP下获取上个月、下个月、本月的日期(strtotime,date)
2014/02/02 PHP
PHP中Memcache操作类及用法实例
2014/12/12 PHP
PHP微信红包API接口
2015/12/05 PHP
php实现数组中出现次数超过一半的数字的统计方法
2018/10/14 PHP
js如何实现设计模式中的模板方法
2013/07/23 Javascript
jquery 快速回到页首的方法
2013/12/05 Javascript
动态加载jquery库的方法
2014/02/12 Javascript
Js中使用hasOwnProperty方法检索ajax响应对象的例子
2014/12/08 Javascript
jQuery头像裁剪工具jcrop用法实例(附演示与demo源码下载)
2016/01/22 Javascript
JavaScript 经典实例日常收集整理(常用经典)
2016/03/30 Javascript
使用JQuery 加载页面时调用JS的实现方法
2016/05/30 Javascript
js html5 css俄罗斯方块游戏再现
2016/10/17 Javascript
jquery实现文本框的禁用和启用
2016/12/07 Javascript
工作中常用的js、jquery自定义扩展函数代码片段汇总
2016/12/22 Javascript
vue axios用法教程详解
2017/07/23 Javascript
详解vue中引入stylus及报错解决方法
2017/09/22 Javascript
微信小程序实现页面跳转传值的方法
2017/10/12 Javascript
通过js动态创建标签,并设置属性方法
2018/02/24 Javascript
JS实现checkbox互斥(单选)功能示例
2019/05/04 Javascript
vue权限问题的完美解决方案
2019/05/08 Javascript
JS实现压缩上传图片base64长度功能
2019/12/03 Javascript
JS实现手写 forEach算法示例
2020/04/29 Javascript
JavaScript图像放大镜效果实现方法详解
2020/06/28 Javascript
JavaScript数组常用的增删改查与其他属性详解
2020/10/13 Javascript
[11:27]《一刀刀一天》之DOTA全时刻20:TI4总奖金突破920W TS赛事分析
2014/06/18 DOTA
用Python编写一个简单的FUSE文件系统的教程
2015/04/02 Python
python将excel转换为csv的代码方法总结
2019/07/03 Python
Python空间数据处理之GDAL读写遥感图像
2019/08/01 Python
完美解决keras 读取多个hdf5文件进行训练的问题
2020/07/01 Python
CSS3中的content属性使用示例
2015/07/20 HTML / CSS
全球500多个机场的接送服务:Suntransfers
2019/06/03 全球购物
高中学生干部学习的自我评价
2014/02/21 职场文书
《孔子游春》教学反思
2014/02/25 职场文书
法人代表证明书格式
2014/10/01 职场文书
Spring mvc是如何实现与数据库的前后端的连接操作的?
2021/06/30 Java/Android