对象、数组传递赋值之引用传递
程序员文章站
2022-07-15 22:01:50
...
开发过程中经常会遇到如下情况,将一个对象赋值给另一个对象,修改后者,前者也随之改变,场景代码如下:
控制台输出入下图:
造成以上现象的原因,个人总结如下:
对象,数组都是引用类型数据,在上述赋值操作过程中,仅仅是将存储在栈中的路径进行的赋值,而未对堆中的数据进行赋值,所以两者依然依赖相同的堆中存储的数据,改变后者,实际上是通过栈中存储的路径改变了堆中的数据,顾两者依赖的数据(栈所指向的堆中数据)发生改变,从而影响力前者;
为避免以上场景的发生,我们在开发过程中可通过结构重组或执行方法脚本(工具函数)等方式将引用传递改为值传递,具体操作可参考如下代码:
1.对于层级结构简单的数据可通过结构重组的方式进行深拷贝(值传递),demo案例如下:
<script>
var objA = {name:'小明',age:20};
// 通过解构重组的方式赋值
var objB = {...objA};
console.log(objA,objB);
// 改变objB的属性;
objB.name = '小王';objB.age=18;
console.log(objA,objB);
</script>
控制台输出如下:
2.对于层级结构复杂的数据可通过执行方法脚本(工具函数)的方式进行深拷贝(值传递),demo案例如下:
ps:方法代码如下:
/*
* @method refactor赋值函数
* @param data 数据源
* @return 处理后的数据
*/
function refactor(data){
// 初始化返回数据
let refactorData = null;
// 判断入参是否是数组
if(Object.prototype.toString.call(data) === '[object Array]'){
// 改变返回数据格式
refactorData = [];
// 循环入参将数据进一步解析
for(let i=0; i<data.length; i++){
// 判断子元素是否是对象或数组 如果是对象或数组进行方法自调用处理数据
if(typeof data[i] ==='object'){
refactorData.push(this.refactor(data[i]));
}else{
refactorData.push(data[i]);
}
}
// 判断入参是否是数组
}else if(Object.prototype.toString.call(data) === '[object Object]'){
// 改变返回数据格式
refactorData = {};
// 循环入参将数据进一步解析
for(let i in data){
// 判断子元素是否是对象或数组 如果是对象或数组进行方法自调用处理数据
if(typeof data[i] ==='object'){
refactorData[i] = this.refactor(data[i]);
}else{
refactorData[i] = data[i];
}
}
// 判断入参是否是其他类型数据
}else{
refactorData = data;
}
// 返回处理后的数据
return refactorData;
}
(1)通过方法进行赋值:
// 执行方法脚本(工具函数)的方式进行赋值
var objA = [{name:'小明',age:20},[1,2,3,[4,5]],6];
var objB = refactor(objA);
console.log(objA,objB);
(2)输出结果如下:
(3)改变后者属性:
// 执行方法脚本(工具函数)的方式进行赋值
var objA = [{name:'小明',age:20},[1,2,3,[4,5]],6];
var objB = refactor(objA);
//改变后者属性值
objB[0].name = '小王';
objB[1][0] = 0;
console.log(objA,objB);
(4)控制台输出如图:
综合以上demo案例,浅谈个人对引用数据赋值的理解,不足之处欢迎指正~
博客更新:最近接触了一个前端大佬,接触到了一个更简便的数据引用传递改为值传递的方法,仅需一行代码,是的,你没看错仅需一行代码,并且不需要封装,案例代码如下:
<script>
var objA = {a:[1,2,[3,4]],b:{c:3}};
var objB =JSON.parse(JSON.stringify(objA));
objB.b.c=1;
console.log(objA,objB)
</script>
代码解析:先将数据类型转为字符串,再将数据转换为json对象;
控制台输出如下: