第4章 变量、作用域和内存问题
4.1 基本类型和引用类型的值
4.1.1动态属性
ECMAScript变量可能包含两种不同数据类型的变量:基本类型值和引用类型值。五种基本数据类型:Undefined、Null、String、Boolean、Number;引用类型指那些可能有多个值构成的对象。只能给引用类型值动态地添加属性,不能给基本类型值这样添加。
1 2 3 | var person = new Object(); person.name="Name"; alert(person.name); |
4.1.2复制变量值
对于基本变量类型值,如果从一个变量向另一个变量复制值,会给新变量分配空间,再存入变量值;对于引用类型值,同样也会将存储在变量对象中的值复制一份放在为新变量分配的空间中,然而,这个值的副本实际是一个指针,指向存储在堆中的一个对象。
通俗来讲,对于创建的新的基本变量,改变值对旧变量无影响。对于创建的新的引用类型变量,改变值,则新旧变量的值都被改变。
1 2 3 4 5 6 7 8 | //引用类型变量 var obj1 = new Object(); obj2 = obj1; obj1.name = "name"; alert(obj2.name) //结果为"name" //基本类型变量 var num1 = 5; var num2 = num1; //值为5,改变num2,对num1的值无影响 |
4.1.3参数传递
ECMAScript中函数的参数在内部是一个数组来表示的,实际上,在函数体内可以通过arguments对象来访问这个参数数组,从而获取传递的每一个参数。arguments对象只是与Array类似,但是并不是Array实例。
1 2 3 4 | function sayHi(){ alert("Hello "+arguments[0] +","+arguments[1]); } sayHi("Javascipt","world"); //Hello Javascript,world |
若定义了两个名字相同的函数,则该名字只属于后定义的函数,不存在函数重载。
ECMAScript中所有函数的参数都是按值传递。
在向参数传递基本类型的值时,被传递的值会复制给一个局部变量,也就是arguments对象中的一个元素。函数内部,参数num的值被加上10,不会影响函数外部的全局变量count变量。
1 2 3 4 5 6 7 8 | function addTen(num){ num+=10; return num; } var count = 20; var result = addTen(count); alert(count); //20 全局变量count的值不改变 alert(result); //30 |
对于引用类型——对象来说。
1 2 3 4 5 6 7 | function setName(obj) { obj.name = "Nicholas"; } var person = new Object(); setName(person); alert(person.name); //Nicholas |
在函数内部,person和obj引用的是同一个对象。但是值得注意的是,虽然局部作用域中修改的对象会在全局作用域反映出来,但参数并不是按引用传递的。以下代码证明了对象是按值传递的。
1 2 3 4 5 6 7 8 9 | function setName(obj){ obj.name = "Nicholas"; //person.name = "Nicholas" obj = new Object(); //局部对象,函数执行完后销毁 obj.name = "Greg"; } var person = new Object(); setName(person); alert(person.name); //"Nicholas" |
如果person是按引用传递的,那么person就会自动被修改为指向name属性值为“Greg”的新对象,从代码看,显然不是。函数内部重写obj时,该变量引用的是一个局部对象。