JavaScript中有一个非常重要的知识点,那就是引用传递。顾名思义,就是利用引用来传递变量的值。在函数调用时,函数的形参将会使用与实参相同的内存地址,所以,当形参的值发生改变的时候,实参的值也会同步被改变。本文将详细介绍JavaScript中引用传递的相关知识。
一、基本概念
引用是一个指向对象存储地址的值。它是一种特殊的数据类型,包括函数、数组、对象、以及其他的一些数据类型。变量保存的是该对象之所在的内存地址,而不是实际的值。
例如:我们定义一个原始数据类型的变量a,一个引用类型的变量b。
var a = 1;
var b = {name: 'peter', age: 30};
变量a保存了一个数字1,而变量b保存了一个地址,在内存中,这个地址指向一个具有name和age属性的实际对象。
二、传递方式
JavaScript中通过引用的方式来传递参数。当函数需处理对象的数据时,他要先取得该对象的引用,再通过该访问对象的属性或从对象中返回值。
传递变量时,传递的值是变量所在对象的地址,而不是变量的值本身。如下面例子:
var obj = {a: 1}; function fn(x){ x.a = 2; } fn(obj);//调用函数 console.log(obj.a);//输出2在调用函数fn时,参数obj的值其实是obj所在的地址,当在函数内部修改了obj.a的值为2时,obj的值也随之被改变了,在最后输出obj.a时,结果为2。 三、对象传递 JavaScript中的对象传递是指,把引用类型的数据作为函数的参数来传递的过程。在函数内部,我们可以修改传递进来的对象的属性,同时,原始对象的值也会随之被修改。
var obj = {name: "peter"}; function fn(x){ x.name = "mary"; } fn(obj); console.log(obj.name);//输出mary在函数fn中,参数x保存了对象obj的一个引用,而不是一个新的对象。当修改x.name的值时,直接影响到了原对象obj的name属性的值,这样的结果就是执行完函数fn之后,原来的name属性值被修改为了“mary”。 四、数组传递 引用传递同样适用于数组类型。我们可以将数组传递给函数,并在函数内部对数组进行操作,这样的改变会表现在原始数组中。
var arr = [1, 2, 3]; function fn(x){ x.push(4); } fn(arr); console.log(arr);//输出[1, 2, 3, 4]在函数fn中,我们将arr数组传递进去,函数内部通过push方法向数组中增加数字4,这样的操作改变了原数组arr的值。所以,在输出arr数组时,他变成了[1, 2, 3, 4]。 五、需要注意的问题 当我们对引用值进行改变的时候,一定要非常小心。因为,任何对引用值的改变都会产生副作用。也就是说,我们可能在某个地方修改了该值,却不知道它会对其他位置造成怎样的影响。 以下示例便是一个常见的问题:
function foo(x){ x.push(4); x = [5, 6, 7]; x.push(8); } var arr = [1, 2, 3]; foo(arr); console.log(arr);//输出[1, 2, 3, 4]在函数foo中,我们通过push方法向数组arr中添加了数字4,在x = [5, 6, 7]这一行,我们创建了一个新数组,并把x指向了这个新数组以替换原数组。之后,我们又通过push方法向数组中添加数字8。但是,在我们输出原数组arr时,结果仍为[1, 2, 3, 4],这是因为,当我们声明了一个新的数组x时,它只是改变了x所指向的内存地址,而不是arr的地址,故结果不会发生变化。 六、总结 引用传递是JavaScript中的一个重要概念,他给我们在开发应用程序时提供了很强的灵活性和扩展性。但是,在操作引用值时,我们必须特别小心,以免不经意间对有意的对象代码造成损失。