今天看了一下关于javascript中关与值传递,引用传递的解释,发现一段有趣的代码,但好像并没发现比较详细的解释。遂自己写一下个人对于该代码片段中的值传递和引用传递的简单理解。
function changeStuff(a, b, c)
{
a = a * 10;
b.item = "changed";
c = {item: "changed"};
}
var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(num, obj1, obj2);
console.log(num);
console.log(obj1.item);
console.log(obj2.item);
// 输出结果
10
changed
unchanged
代码源自此处
正如此处按值传递一节所说,JavaScript 中永远是按值传递(pass-by-value),只不过当我们传递的是某个对象的引用时,这里的值指的是对象的引用。按值传递中函数的形参是被调用时所传实参的副本。修改形参的值并不会影响实参。而按引用传递(pass-by-reference)时,函数的形参接收实参的隐式引用,而不再是副本。
个人把对于上面的代码片中发生的理解写成如下的伪代码。
function changeStuff(var a,var b,var c)
{
a = a * 10;
b.item = "changed";
c = {item: "changed"};
}
var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(var a = num,var b = obj1,var c = obj2);
console.log(num);
console.log(obj1.item);
console.log(obj2.item);
// 输出结果
10
changed
unchanged
形参的作用域(关于作用域的解释,可以去看《你不知道的javascript》作用域一章)在函数而非全局,因为console.log()是全局函数的方法,当console.log()的时候,会直接在全局作用域中找到num,obj1和obj2。
function changeStuff()在console.log()之前调用,其中a = a * 10改变的是形参a的值而非num 的值,c = {item: “changed”}改变的是形参c 的地址而非obj2的地址,但是b.item = “changed”这里是直接对obj1中的item的引用,通过b找到obj1,再通过obj1找到这个对象的地址,从而改变此对象的item的值。所以,最终的结果就是你们看到的obj1.item 的值发生了改变,而num 和obj2.item 没有变化。