在 JavaScript 中是传值(pass by value)还是传引用(pass by reference)呢?通常我们认为传参是原始类型(String, Number…)就是 pass by value,而引用类型(Array, Object)的话,就是 pass by reference。那么事实真的是如此吗?下面通过一些例子来了解一下。
案例
|
|
假设:
- 如果 JS 中是 pass by value,那么例子中,修改
b.item
就不会导致函数外obj1
发生变化; - 如果 JS 中是 pass by reference,那么例子中,修改参数
a
也会生效,变量num
就会变成 100;还有obj2.item
也会变成changed
;
那么 JS 中到底是传值还是传引用呢?答案是 pass by value,只不过对于引用类型,传递的 value 是其引用 reference。技术上,称之为 call-by-sharing
那么对于这个例子,这么解释就通了,
1、对于参数 a
传递的是原始类型,单纯的传递 value,所以,函数 changeStuff
中即使对其进行了修改,也不会影响函数外的 num
2、对于参数 b
, c
传递的是引用类型,那么就是传递了其引用,也即是 b
和 obj1
都指向了 {item: "unchanged"}
,c
和 obj2
也是如此
b.item = "changed";
是修改了其指向对象的的某一个属性,那么b
和obj1
都同时指向的对象就发生变化,变成了{item: "changed"}
c = {item: "changed"};
是修改了参数c
的指向,c
和obj2
此时的指向不同,c
指向的是{item: "changed"}
,而obj2
指向的是{item: "unchanged"}
总结
- Javascript is always pass by value, but when a variable refers to an object (including arrays), the “value” is a reference to the object.
- Changing the value of a variable never changes the underlying primitive or object, it just points the variable to a new primitive or object.
- However, changing a property of an object referenced by a variable does change the underlying object.
Example 1:
Example 2:
其他
1、前段时间在微博上看到阮一峰微博上说,函数参数默认值不是传值调用,例子如下:
那么是不是呢?在评论中,看到有一个比较合理的说法是:其实就是传值调用,只不过每执行一次foo()就传一次新值。传进去的值不会改变,除非再次调用foo()。例子如下:
可以发现,代码执行过程中,虽然外部 x
发生了变化,但是输出的值还一直是 100。
2、pass by value 和 pass by reference 的区别