js变量以及其作用域详解

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

JS变量作用域


代码如下:

<script language ="javascript" type ="text/javascript" >
var a = "change";
function fun() {
alert(a);//输出undefined
var a = "改变了";
alert(a);//输出改变了
}
alert(a);//输出change
fun();
</script>

var定义的是一个作用域上的变量,在第一次输出a之前,JS在预编译分析中已经将a赋值为change,所以第一次输出change,当调用到fun()函数的时候,JS创建一个新的作用域,在输出a之前,初始化所有var变量的值为undefined,所以fun()中第一次输出的是undefined,第二次输出已经给a赋值了,所以输出新的值;两个a在函数里面和外面是不同的两个变量,如:


代码如下:

<script language ="javascript" type ="text/javascript" >
var b;
function fun() {
b = "change";
}
alert(b);//输出undefined
</script>

变量b在函数外面已经定义了,在函数中有给b赋值,但输出的却是undefined。

(0)

相关推荐

  • JavaScript变量作用域_动力节点Java学院整理

    在JavaScript中,用var申明的变量实际上是有作用域的. 如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量: 'use strict'; function foo() { var x = 1; x = x + 1; } x = x + 2; // ReferenceError! 无法在函数体外引用变量x 如果两个不同的函数各自申明了同一个变量,那么该变量只在各自的函数体内起作用.换句话说,不同函数内部的同名变量互相独立,互不影响: 'use stric

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

    每一种语言都有变量的概念,变量是用来存储信息的一个元素.比如下面这个函数: 复制代码 代码如下: 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 : "+t

  • js函数内变量的作用域分析

    本文实例分析了js函数内变量的作用域.分享给大家供大家参考.具体分析如下: 先看一个函数实例: 复制代码 代码如下: <html> <head> </head> <body> <script type="text/javascript"> var a = 5; var c = 3; function t(){  var a = 6;  var b = 10;  document.write(a+'-----'+b);  doc

  • 理解JavaScript变量作用域更轻松

    JavaScript本身作为一门简单的语言,就其变量作用域问题一样令不少人头晕,这主要是因为JavaScript闭包的存在.本文不打算深入讲解JavaScript变量作用域问题(其实本人也没有能力能把这一话题讲的深入些),也不讲"闭包"话题,本文只讨论最实用的JavaScript作用域知识点. 一.JavaScript作用域分类 JavaScript就两种作用域:全局(window).函数级(function).函数级(function)不要理解为"块级(大括号{}级)&qu

  • Javascript变量作用域详解

    变量的作用域指的是变量的可见性,而生命周期则(存活期)则是从另一个角度考察变量. JS中变量的作用域分为全局变量和局部变量,函数内定义的称为局部变量,函数外的称为全局变量.("函数外的称为全局变量"是相对的,另此处讨论的前提是用var显式声明的变量,函数内不用var定义的变量默认是全局变量,当然忽略var声明变量是不赞成的). 复制代码 代码如下: var glob = 4;//函数外声明全局变量 function fun() {     var height = 20; //函数内用

  • JavaScript的变量作用域深入理解

    在学习JavaScript的变量作用域之前,我们应当明确几点: a.JavaScript的变量作用域是基于其特有的作用域链的. b.JavaScript没有块级作用域. c.函数中声明的变量在整个函数中都有定义. 1.JavaScript的作用域链 首先看下下面这段代码: 复制代码 代码如下: <script type="text/javascript" language="javascript"> var rain = 1; function rain

  • 关于JavaScript中var声明变量作用域的推断

    一.迷思!由一段代码引发的疑惑 请看如下代码: 复制代码 代码如下: for(var i=0;i<3;i++) { console.log(j+","+k); for(var j=0;j<3;j++) { var k = j+1; } } console.log(i); 输出结果: undefined,undefined 3,3 3,3 3 如果你是搞c.java等语言的,可能你会不解,为何j.k这种局部变量可以被作用域外的代码访问呢? 如果JavaScript中用var声

  • js变量、作用域及内存详解

    基本类型值有:undefined,NUll,Boolean,Number和String,这些类型分别在内存中占有固定的大小空间,他们的值保存在栈空间,我们通过按值来访问的. (1)值类型:数值.布尔值.null.undefined. (2)引用类型:对象.数组.函数. 如果赋值的是引用类型的值,则必须在堆内存中为这个值分配空间.由于这种值的大小不固定(对象有很多属性和方法),因此不能把他们保存到栈内存中.但内存地址大小是固定的,因此可以将内存地址保存在栈内存中. <script type="

  • JScript中的'var'定义变量的作用域

    都不记得是什么时候看的JScript的语法教程了,里面说在声明变量时忽略var关键字是完全合法的.当时也因为觉得JavaScript是loosely-typed的语言,所以var可能真的就是个摆设.但是事实常常又证明想当然的结果是不可靠的.   看看下面这几个例子的结果就知道问题了:  No.1 var var00 = 0; document.write(var00 + ' '); var var01 = 1; function foo() { document.write(var01); va

  • javascript中的变量作用域以及变量提升详细介绍

    变量作用域"一个变量的作用域表示这个变量存在的上下文.它指定了你可以访问哪些变量以及你是否有权限访问某个变量." 变量作用域分为局部作用域和全局作用域. 局部变量(处于函数级别的作用域)不像其他对面对象的编程语言(比方说C++,Java等等),javascript没有块级作用域(被花括号包围的):当是,javascript有拥有函数级别的作用域,也就是说,在一个函数内定义的变量只能在函数内部访问或者这个函数内部的函数访问(闭包除外,这个我们过几天再写个专题). 函数级别作用域的一个例子

随机推荐