JS函数传参以及遇到的问题

127 阅读2分钟

前言

在最近的开发中遇到了一些问题,定义了一个函数对传入的参数进行处理并返回,但是在操作的过程中发现了源数据也被修改了,这显然是不符合红宝书所说的ECMAScript中都是值传递的说法的,于是又进行了一波深入的学习。

值传递

首先了解一下什么是值传递。所谓的值传递,可以理解简单的理解为将传递的数据拷贝一份作为函数的参数,源数据和函数的参数内存是相互独立的,在函数中修改参数是不会影响源数据的,具体看下面代码

let x = 1
function foo(y) {
   y = 2
   console.log(y) // 2
}
foo(x)
console.log(x) // 1

从上面的代码我们可以看出,在函数中修改了y的值,但是x的值是不会受到影响的,x和y都是独立的空间,这就是所谓的值传递。

遇到的现象

遇到的问题直接为大家献上代码

let obj = { a: 1 }
function foo(x) {
  x.a = 2
  console.log(x.a) // 2
}
foo(obj)
console.log(obj.a) // 2

以上就是我在开发需求中需要的问题,当在函数中修改了参数的值时,源数据也被修改了,这显然是与红宝书所谓的值传递相违背。难道当传递的数据是引用数据类型时,传递参数的形式就变成了引用传递了吗?请看下面的代码。

let obj = { a: 1 }
function foo(x) {
  x = 2
  console.log(x) // 2
}
foo(obj)
console.log(obj) // { a: 1 }

如果说是所谓的引用传递,那么在函数中修改了参数的值,源数据应该也会被修改,但是事实却是相反的。

总结

从以上代码可以看出,当传递的数据类型是基本数据类型时,传递参数的形式确实是值传递。但是当传递的数据类型为引用数据类型时,我们可以理解为是一种共享传递,传递的是该对象的副本,如果对对象整体进行修改,则不会影响到源数据;但是修改对象中的属性,则是相互映射的一种关系,会通过副本找到源数据并进行修改。具体为啥会是这种现象可以参考这篇文章github.com/mqyqingfeng…