值传递还是引用传递
值传递还是引用传递?
当我很嫩的时候,我一度认为 JavaScript
中函数的参数参数传递方式是:
- 当参数为基本类型时,是按值传递;
- 当参数为引用类型时,是按引用传递;
基本数据类型
而使我坚信的依据是什么呢?我们看个例子:
var count = 1;
function fn(num) {
num = num + 10;
return num;
};
var result = fn(count);
console.log(count); // 1
console.log(result); // 11
此时可以看见,count
作为参数被传递给了 fn
函数,然后在函数内部对这个值做了四则运算,然而最终的结果并没有影响到 count
的值,假如是引用传递的话,那么 count
的值也会变为 11
。其它基本类型的值也是如此,有兴趣的小伙伴可以去试试。
因此,我们可以得出结论:当参数为基本类型时,是按值传递。
引用数据类型
接下来我们再看一个参数为引用数据类型的例子:
function fn(obj) {
obj.name = 'Essentric';
};
var person = { name: 'Me' };
fn(person);
console.log(person.name) // Essentric
可以看到,我们创建了一个 person
对象,其有一个 name
为 Me
的属性,将 person
对象传递给 fn
函数之后,我们在函数内部修改了该参数的 name
的值,结果 person
对象的 name
属性值也跟着发生了改变。看到这,有些朋友就开始得出结论了,这不正是引用传递的结果么?然而事情并没有那么简单。
接下来我们再看一个可以推翻这个结论的例子:
function fn(obj) {
obj = { name: 'Essentric' }; // 关键代码
};
var person = { name: 'Me' };
fn(person);
console.log(person.name) // Me
还是上面那个例子,只是我们在函数内部不再是改变 obj
的 name
属性,而是将一个新的对象赋值给了参数 obj
此时,我们 person
对象的 name
属性却 没有 跟着发生变化。这不就推翻了上面的结论了嘛。
事实上,当参数为引用类型时,传递的方式也是 值传递。 传递参数时,实际上是将函数外部的参数拷贝了一份并赋值给函数内部的局部变量。
person
变量保存的是指向堆内存中对象 { name: 'Me' }
的地址,因此传递的参数实际是将该地址复制了一份并传递,所以 person
和 obj
保存的是同一个地址,指向的是同一个对象,故修改 name
属性时,会同步反应到 person
中。而当执行 obj = { name: 'Essentric' }
时,实际是将 obj
指向了另外一个对象,因此之前的指向就被断开了。所以并不会反应到 person
中。因为两者已经没有关联了。
具体的过程可以用一个图来表示:
图比较简陋,可以凑合着理解一下。
总结
函数的参数都是按值传递的。也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。
- 在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量;
- 在向参数传递引用类型的值时,会这个值在内存中的地址复制给一个局部变量;
上一篇: XML流式的查询
下一篇: Linux 系统管理 —— 进程管理