zoukankan      html  css  js  c++  java
  • 浅谈深拷贝 与 浅拷贝

    1.javascript变量包含两种不同数据类型的值:基本类型和引用类型。

    基本类型值指的是简单的数据段,包括es6里面新增的一共是有6种,具体如下:

    number、string、boolean、null、undefined、symbol

    引用类型值指那些可能由多个值构成的对象,只有一种如下:

    object

    在将一个值赋给变量时,解析器必须确定这个值是基本类型值还是引用类型值。基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值。

    引用类型的值是保存在内存中的对象。与其他语言不同,JavaScript 不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。 在操作对象时, 实际上是在操作对象的引用而不是实际的对象。

    2.javascript的变量的存储方式--栈(stack)和堆(heap)

    栈:自动分配内存空间,系统自动释放,里面存放的是基本类型的值和引用类型的地址

    堆:动态分配的内存,大小不定,也不会自动释放。里面存放引用类型的值。

    值传递:当数据传递后发生改变的时候,不会改变原来的数据

    var a=3
    var b=a
    b=4
    console.log(a,b)  //3 4

    引用传递:当数据传递后发生改变的时候,会改变原来数据

    var obj={a:1,b:2}
    var newobj=obj
    newobj.a=3
    console.log(newobj,obj)  //{a: 3, b: 2} {a: 3, b: 2}

    浅拷贝(空间相同)浅拷贝是拷贝引用,拷贝后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响

    遍历

    var obj={data:{a:1,b:2}}
    var newobj={}
    for(var key in obj){
        newobj[key]=obj[key]
    }
    newobj.data.a=3
    console.log(newobj,obj)  //{data:{a: 3, b: 2}} {data:{a: 3, b: 2}}
    Object.assign(target,copytarget)   ES6新增方法
     var obj={data:{a:1,b:2}}
     var newobj=Object.assign({},obj)
     newobj.data.a=3
     console.log(newobj,obj) //{data:{a: 3, b: 2}} {data:{a: 3, b: 2}}

     $.extend(target,copytarget)  这里采用的是第二和第三个参数
     如果第一个参数设置为true,则jQuery返回一个深层次的副本,递归地复制找到的任何对象。否则的话,副本会与原对象共享结构。 未定义的属性将不会被复制,然而从对象的原型继承的属性将会被复制

    var obj={data:{a:1,b:2}}
    var newobj=$.extend({},obj)
    newobj.data.a=3
    console.log(newobj,obj)
    // {data:{a: 3, b: 2}} {data:{a: 3, b: 2}}

    深拷贝(改变了空间)在堆中重新分配内存,并且把源对象所有属性都进行新建拷贝,以保证深拷贝的对象的引用图不包含任何原有对象或对象图上的任何对象,拷贝后的对象与原来的对象是完全隔离,互不影响

    数组方面:

    //将数组或者是类数组对象深拷贝为新数组
    var array2 = Array.from(array1);
    //深拷贝数组  其实就是让它的引用不被传递
    var array2 = [...array1];

    给个空间循环遍历也可 array2
    =[]

    array1.forEach(item
    =>{ return array2.push(item) });
    array2
    =array1.filter(item=>item)
    array2
    =array1.map(item=>item)

       [].slice.call()
      [].slice.apply()

        Array.prototype.slice.call();

      Array.prototype.slice.apply();

     此处省略无数个  可以改变引用地址 或者空间的都可以进行改变
    console.log(array2==array1)

    对象方面

    遍历

    var obj={a:1,b:2}
    var newobj={}
    for(var key in obj){
        newobj[key]=obj[key]
    }
    newobj.a=3
    console.log(newobj,obj)
    // {a: 3, b: 2}  {a: 1, b: 2}

    Object.assign(target,copytarget)

    var obj={a:1,b:2}
    var newobj=Object.assign({},obj)
    newobj.a=3
    console.log(newobj,obj)
    //{a: 3, b: 2}  {a: 1, b: 2}

    $.extend(target,copytarget)

    var obj={a:1,b:2}
    var newobj=$.extend({},obj)
    newobj.a=3
    console.log(newobj,obj)
    //{a: 3, b: 2}  {a: 1, b: 2}
    var obj={data:{a:1,b:2}}
    var newobj=$.extend(true,{},obj)
    newobj.data.a=3
    console.log(newobj,obj)
    // {data:{a: 3, b: 2}} {data:{a: 1, b: 2}}

    JSON.stringify(无法复制函数,原型链没了,对象就是object,所属的类没了

    var obj={data:{a:1,b:2}}
    var newobj=JSON.parse(JSON.stringify(obj))
    newobj.data.a=3
    console.log(newobj,obj)
    
    // {data:{a: 3, b: 2}} {data:{a: 1, b: 2}}
    var obj={a:1,b:2}
    var newobj=JSON.parse(JSON.stringify(obj))
    newobj.a=3
    console.log(newobj,obj)    //{a: 3, b: 2}  {a: 1, b: 2}

    封装适合多层对象嵌套深拷贝

    obj={a:1,b:2,data:{a:1,b:2}}
        function copy(obj) {
            var newobj=$.extend(true,{},obj)
            return newobj
        }
        newobj=copy(obj)
        newobj.data.a=10
        newobj.a=10
        console.log(obj,newobj)
    
        //{a: 1, b: 2, data: {a: 1, b: 2}} {a: 10, b: 2, data: {a: 10, b: 2}}
    obj={a:1,b:2,data:{a:1,b:2}}
        function copy(obj) {
            var newobj=JSON.parse(JSON.stringify(obj))
            return newobj
        }
        newobj=copy(obj)
        newobj.data.a=10
        newobj.a=10
        console.log(obj,newobj)
    
    
        //{a: 1, b: 2, data: {a: 1, b: 2}} {a: 10, b: 2, data: {a: 10, b: 2}}
    obj={a:1,b:2,data:{a:1,b:2}}
        function copy(obj) {
            var newobj={}
            for(var key in obj){
                if(typeof obj[key] == 'object'){
                    newobj[key]=copy(obj[key])
                }else{
                    newobj=Object.assign({},obj)
                }
            }
            return newobj
        }
        newobj=copy(obj)
        newobj.data.a=10
        newobj.a=10
        console.log(obj,newobj)
    
        //{a: 1, b: 2, data: {a: 1, b: 2}} {a: 10, b: 2, data: {a: 10, b: 2}}
    obj={a:1,b:2,data:{a:1,b:2}}
        function copy(obj) {
            var newobj={}
            for(var key in obj){
                if(typeof obj[key] == 'object'){
                    newobj[key]=copy(obj[key])
                }else{
                    newobj[key]=obj[key]
                }
            }
            return newobj
        }
        newobj=copy(obj)
        newobj.data.a=10
        newobj.a=10
        console.log(obj,newobj)
    
        //{a: 1, b: 2, data: {a: 1, b: 2}} {a: 10, b: 2, data: {a: 10, b: 2}}
  • 相关阅读:
    linux下ping命令出现ping: sendto: Network is unreachable
    tiny4412--linux驱动学习(2)
    tiny4412--linux驱动学习(1)
    linux-kernel-4.4 移植 (2)解决上部遗留DMA-PL330的问题
    linux-kernel-4.4 移植 (1)启动
    Busybox构建根文件系统和制作Ramdisk
    tiny4412 --Uboot移植(6) SD卡驱动,启动内核
    select响应事件
    项目总结1
    一个盒子只是显示两行
  • 原文地址:https://www.cnblogs.com/lianqing/p/9172073.html
Copyright © 2011-2022 走看看