基本类型和引用类型
ECMAScript变量可能包含两种不同数据类型的值:基本数据类型值和引用类型值。
基本数据类型为:Undefined,Null,Boolean,Number和String五种。
引用类型为:Object,Array,Date,RegExp,Function。
基本变量值复制
var a = 11;
var b = a;
console.log(b);//11
a = 22;
console.log(a);//22
console.log(b);//11
//b still has not been changed after the a was changed
以上代码说明:值复制(b复制a的值)后的两个变量(a和b)可以参与任何操作而不会相互影响。
对象变量值复制
var obj1 = new Object();
var obj2 = obj1;
obj1.name = ‘MUSTANG‘;
console.log(obj2.name);//MUSTANG
obj1.age = 23;
obj2.age = 24;
console.log(obj1.age);//24
以上代码说明:obj2复制obj1后,两个对象指向的是同一个堆内存(即共享一个堆内存)。
因此任意一个对象(obj1或者obj2)添加/删除属性或者方法都是在堆内存中更改的(如果两个对象拥有同一个属性名或者方法名,则以最后一个为准,即同名时前者被后者覆盖)。
参数的传递
function add(num){
num += 20;
return num;
}
var a = 10;
var result = add(a);
console.log(result);//30
console.log(a);//10
以上代码说明:参数是按值传递的,如果num是按引用传递,那么a的值也将为30。因为引用传递是通过堆内存来传递的。
一个有趣的例子
//#1
function setName(obj){
obj.name = ‘MUSTANG‘;
}
var horse = new Object();
setName(horse);
console.log(horse.name);//MUSTANG
//---------------------------------
//#2
function setName(obj){
obj.name = ‘MUSTANG‘;
obj = new Object();
obj.name = ‘SHELBY‘;
}
var horse = new Object();
setName(horse);
console.log(horse.name);//MUSTANG
//still MUSTANG
以上代码说明:结合#1看#2,首先执行setName()
时参数按值传递,但是此时的参数是一个对象,对象则是按引用传递。
因此当执行setName()
时,obj对象(即person对象)添加了name属性。
前面讲到,对象添加/删除属性或者方法都是在堆内存中操作的,因此外部person也会添加name
属性。
因此执行console.log(horse.name)
得到的是’MUSTANG’
而不是’SHELBY’
。
至于为什么obj = new Object(); obj.name = ‘SHELBY‘;
不会生效是因为此时的obj是局部变量,而且此时的obj又是另外一个堆内存了,所以并不会影响外部结果。
文章说明:
参考资料文献:《javascript高级程序设计》(第3版) 第四章
水平有限,欢迎指正。