欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

对象、数组传递赋值之引用传递

程序员文章站 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对象;

控制台输出如下:

对象、数组传递赋值之引用传递