赋值、深拷贝、浅拷贝、堆和栈

首先介绍一下JavaScript的数据类型有哪些:

普通数据类型:string、number、undefined、Null、Boolean、

引用数据类型:object(function、Array、Date)

 介绍一下他们的储存方式:

浅拷贝和赋值的区别:

首先是赋值:(看代码)

    let person = {name:'彭于晏'} 

    let person1 = person
    person1.name = '胡歌'
    console.log(person1);

 输出:

此时是将person赋值给person1,而person1将名字改成了“胡歌”,所以内存中的数据发生了改变

 (看图):

 此时,他们两个指向的是同一个地址,后者把前者的值改变

 ------------------------------------------------------------------------------------------------------------------

此时,我们再来说一说浅拷贝

浅拷贝首先要创建一个新对象(看代码):

补充:hasOwnProperty() 方法用来检测一个属性是否是对象的自有属性,而不是从原型链继承的

let person = {name:'彭于晏'}  
function shallowCopy(source){
        let newObj = {}
        for(var i in source){
            if(source.hasOwnProperty(i)){
                newObj[i]=source[i]
            }
        }
        return newObj
    }

    var person1 = shallowCopy(person)
    person1.name='胡歌'

    console.log("person",person);
    console.log("person1",person1);

输出:

此时两个值就是不一样的,

这就是浅拷贝和赋值的区别

浅拷贝需要创建一个新的对象,指向一个新的地方,而赋值是没有的

 拷贝值:如果属性是一般数据类型,拷贝的就是一般数据类型的值

                如果对象数应用数据类型,那么拷贝的就是内存中的地址

我们再来看一段代码(浅拷贝): 

 let person = {name:'彭于晏',hobby:['运动','唱歌','游泳']} 
 function shallowCopy(source){
        let newObj = {}
        for(var i in source){
            if(source.hasOwnProperty(i)){
                newObj[i]=source[i]
            }
        }
        return newObj
    }
    var person1 = shallowCopy(person)
    person1.name='胡歌'
    person1.hobby[1]='吃饭'
    console.log("person",person.hobby);
    console.log("person1",person1.hobby);

输出:

而此时,person 和person1 中的 hobby 变成了同样的值,为什么会出现这样的情况呢:

        1.因为刚刚说过,拷贝的如果是一般数据类型,拷贝的就是一般数据类型的值,

而拷贝的是引用数据类型,拷贝的则是内存中的地址,

        2.因为hobby 是一个数组,拷贝的是其内存中的地址,此时,person1 和 person 指向的是同一个内存地址,所以,更改person1 的值,原数据也会跟着改变

简单来说,如果浅拷贝碰到引用数据类型的话,前后的数据是互相影响的

 -----------------------------------------------------------------------------------------------------------------

 深拷贝:

深拷贝和浅拷贝的区别:如果属性是引用数据类型的话,就会开辟一个新的空间

我们先来看代码

    function deepClone(obj1={}){
        if(typeof obj1==null || typeof obj1!=='object'){
            return obj1
        }
        let newObj;
        //判断对象还是数组
        if(obj1 instanceof Array){
            newObj=[]
        }else{
            newObj={}
        }
        for(let i in obj1){
             newObj[i]=obj1[i]
        }
        return newObj
    }

    let obj = {
        age:30,
        name:'彭于晏',
        hobby:['运动','唱歌','游泳']
    }
    let obj2 =deepClone(obj)
    obj2.name='胡歌'
    obj2.hobby[1]='吃饭'
    console.log(obj2,obj);

输出:

 如果代码这么写的话,基本数据类型是可以实现拷贝,而且不会影响原数据,

但是如果是 引用数据类型的话,依然会影响到原来的数据,所以我们需要使用递归函数

  function deepClone(obj1={}){
        //判断判断是否是空值和 不是object 对象,否则,会 return obj1
        if(typeof obj1==null || typeof obj1!=='object'){
            return obj1
        }
        let newObj;
        if(obj1 instanceof Array){
            newObj=[]
        }else{
            newObj={}
        }
        for(let i in obj1){
            if(obj1.hasOwnProperty(i)){
                newObj[i]=deepClone(obj1[i]) //这里调用递归函数,在上面会进行判断,和退出递归
            }
        }
        return newObj
       
    }

    let obj = {
        age:30,
        name:'彭于晏',
        hobby:['运动','唱歌','游泳']
    }
    let obj2 =deepClone(obj)
    obj2.name='胡歌'
    obj2.hobby[1]='吃饭'
    console.log(obj2,obj);

 输出:

此时就是实现了深拷贝

------------------------------------------------------若有不对的地方请留言 

猜你喜欢

转载自blog.csdn.net/Cat_LIKE_Mouse/article/details/121281748