美文网首页Web 前端开发 程序员
因对象深拷贝而思——引用数据类型&基本数据类型

因对象深拷贝而思——引用数据类型&基本数据类型

作者: 熊猫饲养员文文 | 来源:发表于2019-03-11 17:29 被阅读0次

    先看一个实例

    let a = [1,2,3];
    let b = a;
    console.log(b);          //[1,2,3]
    b[0] = 0;
    console.log(a);          //[0,1,2]
    

    那么问题来了,在修改了b数组的元素之后,为什么a数组的元素也发生了变化了呢?
    在说明这个问题之前我们需要了解JavaScript的数据类型。

    基本数据类型&引用数据类型

    在学习编程语言时,无论哪种语言都需要先了解该语言环境的数据类型,大多数编程语言中的数据类型都大同小异,在JavaScript中的数据类型大致分为“基本数据类型”和“引用数据类型”两种。

    基本数据类型

    基本数据类型分为NumberStringBooleanNullUndefined,基本数据类型指的是简单的数据段;

    let a = 'hello';
    let b = a;
    b = 'javascript';
    

    在以上的代码中,我们定义了变量a并且赋值了一个字符串‘string’给他,接着定义一个变量b并且将a赋值给b;那么按照我们正常的理解来说,a和b是等价的,至少值都是‘string’,但是实际在代码的运行环境里呢,他们是毫不相关的两个东西。我们来了解一下以上代码在内存中的表现。


    image.png

    在创建了一个a的副本b后,由于基本数据类型的原因,a、b两个变量在内存中是两个相互独立的,任意一个的变化都是自己本身的变化,不对其他变量造成影响。

    引用数据类型

    即对象型类型,如:ObjectArrayFunction等,指的是有多个值构成的对象。和基本数据类型不同的是,引用数据类型不能直接操作内存中的值,而是通过操作数据的引用地址(指针)。

    let obj = {name:'xx',age:20};
    let obj1 = obj;
    obj1.name = 'yy';
    console.log(obj);         //{name:'yy',age:20}
    

    改变了obj1对象name属性的值,原始对象obj的name属性值也发生了相同的变化,引起这样的“bug”在于obj和obj1都指向了一个相同的内存地址相同的一个对象,自然在对一个对象引用的属性值操作时,对象本身也会变化。

    解决方案

    如果有一个需求需要保留原始对象,而操作拷贝出的对象,那么简单的新建变量赋值就不能解决这样的问题。可能在开发过程中或者是面试时,都会听到浅拷贝、深拷贝这样的概念,那么在这篇文章后,相信对于这两个概念应该会是印象深刻。对于深拷贝这样的操作就是为了避免对原始数据的误操作。

    /**
     * 引用数据类型的深拷贝
     * @param {*} p : 需要拷贝的原始数据
     * @param {*} c : 拷贝后输出的数据
     */
    function deepCopy(p, c) {
        var c = c || {};
        for (var i in p) {
            if (typeof p[i] === "object") {
                c[i] = (p[i].constructor === Array) ? [] : {};
                deepCopy(p[i], c[i])
            } else {
                c[i] = p[i]
            }
        }
        return c;
    }
    

    相关文章

      网友评论

        本文标题:因对象深拷贝而思——引用数据类型&基本数据类型

        本文链接:https://www.haomeiwen.com/subject/yipbpqtx.html