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

这里讨论一下我对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的存取,实际上都是操作的同一块内存区域。如果希望重新分配内存空间存储引用型变量,那么我就需要使用克隆方法或者自定义方法来复制引用变量的数据。

(0)

相关推荐

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

    这里讨论一下我对Javascript中变量相关细节的认识,有不当之处欢迎来批. 一.变量的类型 Javascript和Java.C这些语言不同,它是一种无类型.弱检测的语言.它对变量的定义并不需要声明变量类型,我们只要通过赋值的形式,可以将各种类型的数据赋值给同一个变量.例如: i=100;//Number类型 i="variable";//String类型 i={x:4};//Object类型 i=[1,2,3];//Array类型 JS的这种特性虽然让我们的编码更加灵活,但也带来了

  • JS中BOM相关知识点总结(必看篇)

    window对象 ECMAScript是JavaScript的核心,但是如果要在web中使用javascript,那么BOM(浏览器对象模型)才是真正的核心.BOM提供了很多对象,用于访问浏览器的功能,这些功能与任何网页内容无关. window对象:BOM的核心对象是window,它表示浏览器的一个实例.在浏览器中,window对象有双重角色,它既是通过javascript访问浏览器窗口的一个接口,又是ECMAScript规定的Global对象. 因此,所有全局作用域中声明的变量.函数都会变成w

  • 深入内存原理谈JS中变量存储在堆中还是栈中

    目录 一.装不进冰箱的大象 二.影分身的字符串 三.如朕亲临的 '奇球' 四.扑朔迷离的数字 五.小结:基本类型到底存在哪里? JavaScript中基本类型存储在堆中还是栈中? ---- 不基本类型的基本类型 看到这个问题,相信大家都觉得这个题目实在基础的不能再基础了.随手百度一下,就能看到很多人说:基本类型存在栈中,引用类型存在堆中. 真的这么简单么? 一.装不进冰箱的大象 让我们看一下这段代码: 在这里,我们声明了一个67MiB大小的字符串,如果字符串真的存在栈中,这就不好解释了.毕竟,v

  • js中变量的连续赋值(实例讲解)

    今天遇到了一个连续赋值的经典案例,网友们给出的答案也是五花八门,看起来有些繁琐,我也来说说自己的看法. 下面就是这个经典案例: var a = {n: 1}: var b = a; a.x = a = {n: 2}: console.log(a); console.log(b); console.log(a.x); console.log(b.x): 我们先来看一下普通连续赋值,即:变量赋值的类型是数据类型值 var a=3; var b=a=5; console.log(a); console

  • JS中判断null的方法分析

    本文实例讲述了JS中判断null的方法.分享给大家供大家参考,具体如下: 以下是不正确的方法: var exp = null; if (exp == null) { alert("is null"); } exp 为 undefined 时,也会得到与 null 相同的结果,虽然 null 和 undefined 不一样. 注意:要同时判断 null 和 undefined 时可使用本法. var exp = null; if (!exp) { alert("is null&

  • JS中parseInt()和map()用法分析

    本文实例讲述了JS中parseInt()和map()用法.分享给大家供大家参考,具体如下: parseInt()的几个例子 var b = parseInt("01"); alert("b="+b); var c = parseInt("09/08/2009"); alert("c="+c); 结果:b=1,c=0 parseInt()用来解析字符串,返回整数,有几个特点: 1.无视被解析字符串最前和最后的空格,即:"

  • JS中apply()的应用实例分析

    本文实例讲述了JS中apply()的应用.分享给大家供大家参考,具体如下: 先从Math.max()函数说起,Math.max后面可以接收任意个参数,最后返回所有参数中的最大值. 比如: alert(Math.max(5,8));//8 alert(Math.max(5,7,3,1,9,2));//9 但是在很多情况下,我们需要找出数组中最大的元素. 比如: /* * 找出数组中最大的数 */ var arr = [1,4,9,6]; //alert(Math.max(arr));//NaN,这

  • JS中浮点数精度问题的分析与解决方法

    目录 前言 问题的发现 浮点数运算后的精度问题 toFixed奇葩问题 为什么会产生 浮点数的存储 浮点数的运算 解决方法 解决toFixed 解决浮点数运算精度 附:JS浮点数精度问题的一些实用建议 总结 前言 最近在做项目的时候,涉及到商品价格的计算,经常会出现计算出现精度问题.刚开始草草了事,直接用toFixed就解决了问题,并没有好好的思考一下这个问题.后来慢慢的,问题越来越多,连toFixed也出现了(允悲),后来经过搜索网上的各种博客和论坛,整理总结了一下. 问题的发现 总结了一下,

  • JS中getYear()和getFullYear()区别分析

    js中得到当前年份做法是var dayObj=new Date(); dayObj.getYear()来得到年份,我前面写过这样会出现浏览器的兼容性的问题,就是在IE中能得到我们想要的结果但是在FF中就不行了,和我们要的结果相差1900年.当时我的做法是: var dayObj=new Date(); var myYears = ( dayObj.getYear() < 1900 ) ? ( 1900 + dayObj.getYear() ) : dayObj.getYear(); docume

  • js中this的用法实例分析

    本文实例分析了js中this的用法.分享给大家供大家参考.具体分析如下: 实例1:第一种调用this的方法--以函数形式调用.它代表全局对象window 复制代码 代码如下: <script type="text/javascript"> function t(){  alert(this);//这里this表示window对象. } t(); </script> 实例2:第二种调用this的方法--以对象属性的形式调用.它代表该对象.实例中onclick为p元

随机推荐