js原理:函数参数到底是值传递还是引用传递?

78 浏览发布于 作者 Yang (欢迎转载-请注明出处链接)留下评论分享按钮

一、

有的人说是按值传递,因为:

var a = 1;
function box(n) {
    n++;
    console.log(n);
}
box(a);//2
console.log(a);//1

可以看到,a 为基本类型值时,函数内部对传入的 a 进行修改,并没有影响到外部的 a 变量。

有的人说是按引用传递的,因为:

var a = {name:"zou"};
function box(n) {
    n.name = "yang";
    console.log(a);
}
box(a);//{name: "yang"}
console.log(a);//{name: "yang"}

可以看到,a 为对象时,函数内部对传入的 a 进行修改,成功影响到外部的 a 变量。

又有人说,如果对象是按引用传入函数的,那么怎么又无法在函数内对该对象重新赋值呢:

var a = {name:"zou"};
function box(n) {
    n.name = "yang";
    console.log(a);

    n = {}; //将 n 重新赋值为空对象

}
box(a);//{name: "yang"}
console.log(a);//{name: "yang"}

上面函数内部对 n 修改,影响到了传入的 a 对象,对 n 再重新赋值,却又没有影响到。

二、

《js高级程序设计》给出了答案:ECMAScript中所有函数的参数都是按值传递的。

这里的值传递,跟我们理解的普通的值的传递有那么点点“区别”,这里的值,传递的其实是一个该参数的 副本拷贝,该副本作用域在该函数内。

在按值调用中,对参数表达式进行求值,并将结果值绑定到函数中的相应变量(通常通过将值复制到新的内存区域中)

引用自:Evaluation strategy

  • 基本类型值的传递如同 基本类型变量的复制一样,(复制出来了一个值相等的基本类型副本)
  • 引用类型值的传递,则如同 引用类型变量的复制一样。(复制出来了一个引用地址相同的副本)


此时,我们在函数内对参数的修改,只是对传入的原变量的副本进行的操作,所以基本类型不会受影响,而引用类型因为指向的都是同一个堆内存地址,所以会受影响。但是我们重新对 引用类型副本 重新赋值,相当于是重新指定一个新地址了,不会影响到原引用类型。

三、最后附一个书上的例子,可以了解下:

想要打赏,请点击这里

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注