javascript权威指南,第4章,变量

4.1 什么是变量?

变量是一个和数值相关的名字。我们经常说,变量“包含”或者“存储”了一个值。有了变量,在程序中就可以存储和操作数据了。所以说,变量就是一个用于存储数值的一个名字。

4.2 变量的类型:

Javascript是非类型(untype)值的,这就以为着javascript变量可以存放任意类型的的值。因为缺少类型规则,javascript可以快速的将一种类型的值转换成另一种类型的值。例如你想做这样的定义,var string = "s"+10,10是数字,这时候javascript就降10转化为字符串10连接在s后面,结果string = "s10"。相比之下,c,C++是强类型语言,c,c++的变量只能存放它声明了的特定类型的变量。

4.3 变量的声明

在javascript程序中使用变量之前,必须先声明。变量使用关键字 var 声明,例如,var i; var m;

也可以使用一个var 关键字声明多个变量 var i,m;

还可以在将变量声明和初始化绑定在一起 var i = 10; var string = "message";

如果一个变量声明,但是并没有初始化。虽然这个变量声明了,但是在给它存入一个值之前,它的初始值为“undefined”;

由于var声明的变量是永久性的,用delete运算符来删除这些变量将会引发错误。

重复的声明和遗漏的声明

使用var多次声明同一变量是合法的。单如果想读取一个未声明变量的值,javascript会生成一个错误。如果尝试给一个未声明的变量赋值,javascript会隐式声明该变量。但是隐式声明的变量为全局变量,即使是只是在一个函数内使用。

4.4 变量的作用域

变量的作用域,通俗讲就是变量的在哪个区域内起作用。全局作用域是全局的,即在javascript代码中处处都有定义。局部作用域,只在局部有效。在函数内部声明的变量和函数的参数,就只在函数体内有定义,它们是局部变量。

在函数体内,局部变量优先级比同名的全局变量优先级高。如果给一个局部变量或参数声明的名字和全局变量相同,那么久有效的隐藏了这个全局变量。

例如

var scope = "global";

function checkscope(){

   var scope = "local scope";

   document.write(scope);

}

checkscope(); //输出 local scope;

在全局变量声明时,可以不使用关键词var,但是声明局部变量时,一定要加var,否则,他会改变全局变量的值。

<script type="text/javascript">
   scope = "global"; //声明全局变量,没有使用关键字var
   function checkscope(){
      scope = "local";//声明局部变量,没有使用关键字var,改变了全局变量的值
      document.write(scope);//使用全局变量的值
      myscope = "local";//声明一个新的全局变量
      document.write(myscope);  //使用新的全局变量
   }
   checkscope();//输出 locallocal
   document.write(scope);//输出local
</script>

4.4.1 没有块级作用域

什么是块级作用域:任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。

函数作用域:定义在函数中的参数和变量在函数外部是不可见的。

c,c++拥有块级作用域

一个c语言的例子

void main(){

  int i=2;

  i--;

  if(i){

  int j=3;

}

printf("%d\n",j);

}

结果为 “use an undefined variable:j”,因为c语言拥有块级作用域,j在if块中定义,块外无法访问

看一个js的例子

function test(){

   for(var i=0;i<3;i++){}

   alert(i);

}

test();//结果i=3

换句话说i能够访问在for块中定义的i,就说明js没有块作用域,但只有函数作用域,即在函数任何部分定义的变量,在该函数中的任何地方都可以访问;

4.4.2

未定义的变量和未赋值的变量

未定义的变量:从未声明的变量;

为赋值的变量:声明过,但是没有初始化;

之间的区别

var i;//定义一个未赋值的变量,调用时为undefined

alert(u);//定义一个未声明的变量,调用时会报错

u = 3; //给一个未声明的变量赋值来声明这个变量

4.5 基本类型和引用类型

但是字符串是一个特例,具有可变大小,但是我们希望javascript只是复制字符串的引用而不是他的内容。

4.6 垃圾收集

因为引用没有固定类型。javascript每次创建字符串,数组,解释器必须分配内存存储那个实体。javascript可以使用垃圾收集的方法去释放内存。javascript的解释器确定程序中的一个对象是无用的时候(程序中使用的变量再也无法引用这个对象了),即不需要这个对象,可以把它占用内存释放掉了

var s = "hello";

var u = s.toUpperCase();

s = u;

代码运行之后,就不能再获得原始的字符串“hello”,因为程序中没有变量再引用它。系统检测到这一事实后,就会释放该字符串的存储空间。

4.7

4.7 javascript预编译与运行期过程

javascript这种解释型语言,分为两个阶段:编译期(类似于预编译,一下统称为“预编译”)与运行期。

在预编译时期,javascript以函数来划分作用域,然后逐层为其以var声明的变量(建成,var变量)和函数定义开辟内存空间然后为对var变量进行特殊处理,统统赋值为undefined

运行期是在为var变量与函数定义分配空间后立即执行,并且是逐行往下执行的。

来看一个例子

<script type="text/javascript">  
var a=100;  
var b=true;  
function test(){  
    alert(a);  
    alert(b);  
    b=false;  
    alert(b);  
    var a=200;  
    alert(a/2);  
    alert(++Math.PI);  
    alert(Math.PI++);  
}  
test();
</script>

在预编译以后变量的分布情况

javascript的运行期,在var变量和函数定义分布内存之后,立即执行,而且是一步一步执行。

第一行,它为外围作用域的a赋值100;

第一行,它为外围作用域的b赋值true;

第三行,进图test()作用域,简称内围作用域;

第四行,就立即调用内围作用域的a,这时它还没有来得及赋值呢!不过它已经声明过了,因此默认为其赋值为undefined(在预编译阶段,见图),于是alert为undefined

第五行就调用b时,发现test的作用域内没有b,就往外寻找,而b在第二行就赋值为true,于是alert为true。

第六行,为一个赋值操作,把外围的b变量改赋为false。于是到第7行时,alert为false。

作用域总结:变量会首先寻找内围作用域,内围作用域级别比外围高。

原文地址:https://www.cnblogs.com/huanhuan8808/p/3043067.html