标签:
了解参数的传递之前我们来复习下变量的类型,JavaScript中的变量有5个基本数据类型(Undefined, Null, Boolean, Number, String)和引用数据类型(Object,Function,Array等)。
// 声明一个String类型的变量
var str = "string";
// 声明一个引用类型的变量,并添加属性
var person = new Object(); person.name = "Jeremy";
二者的区别主要在于对变量内容保存的方式,基本类型的变量中存储的就是简单的数据段,而引用类型变量存储的是指向对象的引用,比如:
// 基本类型的变量复制,可以看出基本类型变量存储的就是变量的值
var num1 = 5; var num2 = num1; console.log(num2); //5
num1的5与num2的5是完全独立的,这两个变量可以参与任何操作而不会相互影响。下图能够形象的展示复制过程。
// 引用类型的变量复制,可以看出引用变量中存储的是指向对象的引用
// Object对象存储于堆中,而obj1和obj2分别存储了指向此Object对象的引用
var obj1 = new Object(); obj1.name = "Jeremy"; var obj2 = obj1; obj2.name = "James"; console.log(obj1.name); //James
首先变量obj1保存了一个对象的新实例,又给obj1添加一个新属性name,后obj1对象被复制给了obj2,obj2也有了name这个属性,并且访问的地址是跟obj1的name属性是一个地址,所以当修改了obj2的那么属性的话,那obj1的name属性也会改变。下图展示了保存在变量对象中的变量和保存在堆中的对象之间的这种关系。
在JavaScript中无论是基本类型还是引用类型,函数参数都是按值传递的,先来看基本类型:
function test(num) { num += 10; return num; } var num = 10; var res = test(num); console.log(num); //10 外部变量并未受到影响 console.log(res); //20
接下来看引用类型:
function setName(obj) { obj.name = "James"; } var person = new Object(); person.name = "Jeremy"; setName(person);
console.log(person.name);//James 影响到了外部引用变量
?乍一看,这不就是按引用传递吗?怎么会是按值传递呢?之所以是按值传递是因为当调用setName(person)的时候,实际上是把person所指向的对象的引用进行了复制,然后传递给了setName函数,这样在函数setName内部对此引用进行操作时候是会影响到此引用所指向的对象,即外部person所指向的对象。
总的来说,基本类型的参数传递复制的是具体的值,而引用类型的参数传递复制的是这个引用变量存储的对对象的引用。
为了进一步证明引用类型的参数传递是按值传递而不是按引用传递的,请看:
function setName(obj) { obj.name = "James"; obj = new Object(); obj.name = "Leon" } var person = new Object(); person.name = "Jeremy"; setName(person); console.log(person.name);//James
以上代码输出的是James,如果是按引用传递,那么以上代码输出的是Leon。实际上,当执行obj.name = "James"的时候,引用所指向的对象的值已经发生了改变,当在对obj进行覆盖的时候,obj的值是一个指向局部对象的引用,而这个引用无法对外部的对象产生影响,并且此对象会在函数执行结束之后销毁。
标签:
原文地址:http://www.cnblogs.com/jesse-band/p/4467696.html