
JS中传参的类型
2020年7月9日
/
最近同事在使用js的过程中,遇到了一个比较奇葩的问题,使用场景是在js客户端接收到后端传过来的数据之后,他修改了这个数据内容而导致bug无法定位是前端还是后端的问题。
在框架底层,当框架接收到后端消息之后打印了一次日志,日志内容是后端传过来的数据内容。
当数据体传到上层客户时,同事将这个数据体的一部分存储到了临时变量中,并且修改了这个变量中的一个值。
由于某些原因,导致了一个bug,为了解决这个bug需要对数据的值进行排查,结果在分析日志的时候,发现打印的值是有问题的,所以前端同事以为是后端传过来的值有问题,于是,后端同事进行了排查,发现后端传过来的值跟前端打印的值不一样。
导致这个问题的原因其实就跟传参的类型有关系。
我们知道,js中的数据的类型有两大类:
- 字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。
- 对象(Object)、数组(Array)、函数(Function)。
注:Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值。
这两种类型就导致了参数在传递过程中的不同表现:
- 参数通过值传递
- 这种情况下,如果函数改变了参数的值,它不会改变参数的原始值。
- 参数通过引用传递
- 这种情况下,如果函数改变了参数的值,原始值也会改变。
//值传递
var num = 1;
function xx(arg){
arg=2;
}
xx(num);
console.log(num);//1
//对象
var a = {b:1};
function xx(obj){
obj.b=2;
}
xx(a);
console.log(a);//{b: 2}
//数组
var arr = [1,2];
function xx(obj){
obj[0]=2;
}
xx(arr);
console.log(arr);// [2, 2]
需要注意的是,引用传递只有在改变了函数参数(argument
)传递的对象、数组、函数内容,如属性、元素值才会导致原始值被改变,如果直接改变函数参数(parameter
)的引用是不会导致原始值改变的:
//这里注意观察与上面对象代码块的不同
var a = {b:1};
function xx(obj){
obj = {x:2};
}
xx(a);
console.log(a);//{b: 1}
经过对比观察,我们向函数传递a的时候,实际是将引用a的一个副本赋值给obj
,而a
仍然指向{b:1}
。在函数中,我们可以通过更改引用obj来更改对象的值,使用obj.b=2
之后a
的值变为{b: 2}
。但obj = {x:2}
并不影响a的指向,所以a
仍然指向{b:1}
。这也是决定了原始值是否被改变的关键因素,在使用过程中需要特别小心谨慎。
在使用过程中,如果你不想自己的原始值被改变,方法还是很多的,后面我会专门出一篇关于如何防止对象值被改变的文章,现在你自己亲自来试一试吧!


您可能也喜欢

【TS学习系列】4.解构
2018年6月13日
关于隐藏Android应用的状态栏,并全屏显示WebView
2020年4月17日