精华内容
下载资源
问答
  • // 数组浅拷贝,可用concat、slice返回一个新数组的特性来实现拷贝 var arr = ['old', 1, true, null, undefined]; var new_arr = arr.concat(); // 或者var new_arr = arr.slice()也是一样的效果; new_arr[0] = '...

    浅度拷贝:复制一层对象的属性,并不包括对象里面的为引用类型的数据,当改变拷贝的对象里面的引用类型时,源对象也会改变。

    // 数组的浅拷贝,可用concat、slice返回一个新数组的特性来实现拷贝

    var arr = ['old', 1, true, null, undefined];
    var new_arr = arr.concat(); // 或者var new_arr = arr.slice()也是一样的效果;
    new_arr[0] = 'new';
    console.log(arr); // ["old", 1, true, null, undefined]
    console.log(new_arr); // ["new", 1, true, null, undefined]
    

    //浅度拷贝通用方法

    var shallowCopy = function (obj) {
      // 只拷贝对象
      if (typeof obj !== 'object') return;
      // 根据obj的类型判断是新建一个数组还是一个对象
      var newObj = obj instanceof Array ? [] : {};
      // 遍历obj,并且判断是obj的属性才拷贝
      for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
          newObj[key] = obj[key];
        }
      }
      return newObj;
    }
    
    
    深度拷贝:重新开辟一个内存空间,需要递归拷贝对象里的引用,直到子属性都为基本类型。两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。
    
    

    var arr = [‘old’, 1, true, [‘old1’, ‘old2’], {old: 1}]
    var new_arr = JSON.parse(JSON.stringify(arr))
    console.log(new_arr);

    
    
    

    //深拷贝通用方法

    var deepCopy = function(obj) {
      // 只拷贝对象
      if (typeof obj !== 'object') return;
      // 根据obj的类型判断是新建一个数组还是一个对象
      var newObj = obj instanceof Array ? [] : {};
      for (var key in obj) {
        // 遍历obj,并且判断是obj的属性才拷贝
        if (obj.hasOwnProperty(key)) {
          // 判断属性值的类型,如果是对象递归调用深拷贝
          newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
        }
      }
      return newObj;
    }
    
    
    
    展开全文
  • 例如这个例子: 代码如下:var arr = [“One”,”Two”,”Three”];...像上面的这种直接赋值的方式就是浅拷贝,很多时候,这样并不是我们想要得到的结果,其实我们想要的是arr的值不变,不是吗? 方法一:js的sli
  • 如何实现数组深拷贝和浅拷贝? 这里是修真院前端小课堂,每篇分享文从 【背景介绍】【知识剖析】【常见问题】【解决方案】【编码实战】【扩展思考】【更多讨论】【参考文献】 八个方面深度解析前端知识/技能,本...

    如何实现数组深拷贝和浅拷贝?

    这里是修真院前端小课堂,每篇分享文从

    【背景介绍】【知识剖析】【常见问题】【解决方案】【编码实战】【扩展思考】【更多讨论】【参考文献】

    八个方面深度解析前端知识/技能,本篇分享的是:

    【如何实现数组深拷贝和浅拷贝?】


    大家好,我是IT修真院北京总院第24期的学员,一枚正直纯洁善良的web程序员
    今天给大家分享一下,修真院官网JS任务4,深度思考中的知识点——如何实现数组深拷贝和浅拷贝?
    1.背景介绍

     

    用js处理数据的时候经常遇到需要保留原数据的情况,有时把数据赋给新的变量并不能解决问题, 原因是内存中仅保留一份数据。这时候需要制作一份数据的副本。

    只有复杂类型变量(引用类型)存在深拷贝与浅拷贝的问题,而基本类型没有深拷贝的概念。

    要弄明白拷贝,首先要明白js中对象的组成。在js中一切实例皆是对象,具体分为原始类型和合成类型。原始类型对象指的是number、string、boolean等,合成类型对象指的是array、object以及function。

    “堆内存”和“栈内存”


     

     

    基本类型变量作为“值”保存于“栈内存”中。

    引用类型变量作为一个指针保存在栈内存中,指向保存在“堆内存”中的引用类型的值

    堆和栈的区别可以用如下的比喻来看出:

    使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。

    使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。

    深拷贝和浅拷贝

    浅拷贝:拷贝一个变量的时候,复制了栈内存,没有复制堆内存。

    深拷贝:拷贝一个变量的时候,复制了栈内存,同时也复制了堆内存。

    2.知识剖析

    浅拷贝

    浅拷贝可以理解为就是复制一份来引用,所有引用对象都指向一份数据,并且都可以修改这份数据。 对于字符串类型,浅拷贝是对值的拷贝,对于对象来说,浅拷贝是对对象地址的拷贝,也就是复制 的结果是两个对象指向同一个内存地址,修改其中一个对象的属性,则另一个对象的属性也会改变

    深拷贝

    深拷贝则是复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。 深复制不同于浅复制,它会开辟新的内存地址,两个对象对应两个不同的地址,修改 一个对象的属性,不会改变另一个对象的属性

    3.常见问题

    1.如何实现数组深拷贝和浅拷贝?

    2.深拷贝与浅拷贝的优缺点

    4.解决方案

    方法一: 用js的slice函数来实现

    方法二:用js的concat方法

    slice方法

    对于array对象的slice函数,

    返回一个数组的一段。(仍为数组)

    arrayObj.slice(start, [end])

    参数:

    arrayObj

    必选项。一个 Array 对象。

    start

    必选项。arrayObj 中所指定的部分的开始元素是从零开始计算的下标。

    end

    可选项。arrayObj 中所指定的部分的结束元素是从零开始计算的下标。


     

     

    concat方法

    concat() 方法用于连接两个或多个数组。

    该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。

    语法

    arrayObject.concat(arrayX,arrayX,......,arrayX)

    说明

    返回一个新的数组。该数组是通过把所有 arrayX 参数添加到 arrayObject 中生成的。如果要进行 concat() 操作的参数是数组,那么添加的是数组中的元素,而不是数组。


     

     

    浅拷贝的缺点是如果你改变了对象B所指向的内存地址,你同时也改变了对象A指向这个地址的字段。

    深拷贝,这种方式会完全拷贝所有数据,优点是B与A不会相互依赖(A,B完全脱离关联), 缺点是拷贝的速度更慢,代价更大 (可理解为耗费了更多内存空间)。

    5.编码实战

    demo

    6.扩展思考

    其他深拷贝的方法

    json对象的转换方法,两次转换


     

     

     

    7.参考文献

     

    参考一:数组的拷贝

    参考二:原始数据类型和对象类型的区别及深度拷贝解析

    参考三:原生js对象的浅拷贝和深拷贝的总结

    8.更多讨论

    闭包中保存到内存当中的数据是保存到栈中还是堆中的

    都有

    对象的深拷贝是怎么弄得


     

     

     

    视频链接

     

    ppt链接

     

    感谢大家观看

    今天的分享就到这里啦,欢迎大家点赞、转发、留言、拍砖~

    展开全文
  • javascript数组深拷贝途径及对象数组深拷贝 什么是浅拷贝js当中,我们常常遇到数组复制的的情况,许多人一般都会使用“=”来直接把一个数组赋值给一个变量,如: var a=[1,2,3]; var b=a; console.log(b); ...
  • 说赋值、深拷贝浅拷贝之前,先简单过一下数据结构(JavaScript有,那么其他类C语言也会有)。 在程序中,像数组、对象等这类数据都属于堆类型,它们通过地址被某个变量标识指引,也就是说该元素本身其实是个变量...

    有时候我们会碰到这种困惑:
    在这里插入图片描述
    在这里插入图片描述

    说赋值、深拷贝、浅拷贝之前,先简单过一下数据结构(JavaScript有,那么其他类C语言也会有)。
    在程序中,像数组、对象等这类数据都属于堆类型,它们通过地址被某个变量标识指引,也就是说该元素本身其实是个变量(栈类型),保存了对应的堆类型数据的地址。因此,通过常规赋值方法复制某个数组时,其实复制的只是该数组的地址,所指的该数组并没有变,A是数组,声明B,B=A,B保存的是该数组的地址,并不是一个全新的数组,通过B更改数组,A的数组也会被改变。
    在这里插入图片描述

    赋值

    当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。

    浅拷贝

    浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。即默认拷贝构造函数只是对对象进行浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源。
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    Object.assign()

    Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign() 进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。

    在这里插入图片描述
    注意:当object只有一层的时候,是深拷贝

    let obj = {
       username: 'kobe'
    };
    let obj2 = Object.assign({},obj);
    obj2.username = 'wade';
    console.log(obj);//{username: "kobe"}
    
    Array.prototype.concat()
    let arr = [1, 3, {
       username: 'kobe'
     }];
    let arr2=arr.concat();    
    arr2[2].username = 'wade';
    console.log(arr)
    

    在这里插入图片描述

    Array.prototype.slice()
    let arr = [1, 3, {
       username: ' kobe'
     }];
    let arr3 = arr.slice();
    arr3[2].username = 'wade'
    console.log(arr);
    

    在这里插入图片描述

    关于Array的slice和concat方法的补充说明:Array的slice和concat方法不修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。
    原数组的元素会按照下述规则拷贝:
    如果该元素是个对象引用(不是实际的对象),slice 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。
    对于字符串、数字及布尔值来说(不是 String、Number 或者 Boolean 对象),slice 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。
    可能这段话晦涩难懂,我们举个例子,将上面的例子小作修改:

    let arr = [1, 3, {
       username: ' kobe'
       }];
    let arr3 = arr.slice();
    arr3[1] = 2
    console.log(arr,arr3);
    

    在这里插入图片描述

    ES6…

    let {…b} = a; let […b] = a; //当object只有一层的时候,是深拷贝

    深拷贝

    深拷贝:在计算机中开辟了一块新的内存地址用于存放复制的对象。(对属性中所有引用类型的值,遍历到是基本类型的值为止。 )
    实现方式

    JSON.parse(JSON.stringify())
    let arr = [1, 3, {
       username: ' kobe'
    }];
    let arr4 = JSON.parse(JSON.stringify(arr));
    arr4[2].username = 'duncan'; 
    console.log(arr, arr4)
    

    在这里插入图片描述
    原理: 用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。
    这种方法虽然可以实现数组或对象深拷贝,但不能处理函数。

    let arr = [1, 3, {
       username: ' kobe'
    },function(){}];
    let arr4 = JSON.parse(JSON.stringify(arr));
    arr4[2].username = 'duncan'; 
    console.log(arr, arr4)
    

    在这里插入图片描述

    递归方法

    递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝。

    //定义检测数据类型的功能函数
       function checkedType(target) {
         return Object.prototype.toString.call(target).slice(8, -1)
       }
       //实现深度克隆---对象/数组
       function clone(target) {
         //判断拷贝的数据类型
         //初始化变量result 成为最终克隆的数据
         let result, targetType = checkedType(target)
         if (targetType === 'object') {
           result = {}
         } else if (targetType === 'Array') {
           result = []
         } else {
           return target
         }
         //遍历目标数据
         for (let i in target) {
           //获取遍历数据结构的每一项值。
           let value = target[i]
           //判断目标结构里的每一值是否存在对象/数组
           if (checkedType(value) === 'Object' ||
             checkedType(value) === 'Array') { //对象/数组里嵌套了对象/数组
             //继续遍历获取到value值
             result[i] = clone(value)
           } else { //获取到value值是基本的数据类型或者是函数。
             result[i] = value;
           }
         }
         return result
       }
    
    展开全文
  • 谈到拷贝这个东西,我们更多的第一印象就是Ctrl+C,因为这也是我们平时用的很多的方法,今天就再梳理以下javaScript数组深拷贝和浅拷贝的区别, 浅拷贝:两个不同的数组名,但是地址指向同一个位置,比方说 var ...

    谈到拷贝这个东西,我们更多的第一印象就是Ctrl+C,因为这也是我们平时用的很多的方法,今天就再梳理以下javaScript中数组的深拷贝和浅拷贝的区别,
    浅拷贝:两个不同的数组名,但是地址指向同一个位置,比方说
    var list=[1,2,3,4]
    var arr=list
    这个就是属于浅拷贝,当我们修改了后面arr的数组内容时,当面用console.log(list)时,我们会发现list也被改变了。其实我们是没有主动改变list的,这就是他们指向了同一个地址。
    深拷贝:产生新的地址,拷贝数据,地址不是同一个地方,比方说
    var list=[1,2,3,4]
    var arr=[]
    for(var i=0;i<list.length;i++){
    arr[i]=list[i]}
    这个时候,我们就算改变arr数组的内容也不会影响list 的内容,我们用console,log(list)发现他还是他本身
    当然提到这里,很多人会问我怎么知道什么时候用浅拷贝,什么时候用深拷贝呢?
    比方说我们用回调函数时为了保证源数据不改变,这时候就要用到深拷贝,当为值类型的时候一般可以用浅拷贝,一般用引用类型时比方数组。对象这个时候一般多用深拷贝!
    当然还有更多方面的考虑。就边学边看!

    展开全文
  • 数组和对象一样,是引用数据类型 因为指向同一块栈区域,所以当修改arr2时,arr1数组也会发生变化...浅拷贝方法只适用于数组元素是基本类型,如果数组中是对象或者数组,需要进行深拷贝,下面是深拷贝一个通用方法...
  • 利用slice、concat 返回一个新数组的特性来实现拷贝。 var arr = ['old', 1, true, null, undefined]; var new_arr = arr.concat(); new_arr[0] = 'new'; console.log(arr) // ["old", 1, true, null...
  • JS数组深拷贝和浅拷贝

    千次阅读 2018-07-10 19:21:24
    一、浅拷贝js中操作数组过程中,会需要把数组进行备份,直接赋值如下://浅拷贝 直接赋值吧 var arr1 = ["前端","安卓","苹果"]; var arr2 = arr1; arr2[0] = "后端"; ...
  • array 拷贝第一层 slice或者concat,这两个方法都能返回一个新的数组而不影响原来的数组 var a1=["1","2"]; var a2=a1.slice(0); a2.push("2"); console.log(a1,a2)//[1,2] [1,2,2] 扩展运算符 ...对象...
  • JS 数组和对象的浅拷贝和深拷贝 一,数组的浅拷贝 1,浅拷贝 let arr=[1,2,3,4,5]; // es5 const tt01 = arr.slice(); const tt02 = arr.concat(); //es6 const tt03 = [...arr]; tt01.push('dd'); tt0.....
  • 大家好,我是IT修真院郑州分院第十期的学员金俊,一枚正直纯洁善良的程序员 今天给大家分享一下,修真院官网前端任务js4,深度思考中的知识点——如何实现数组深拷贝浅拷贝一、背景知识:什么是数据类型?...
  • 数组的深拷贝和浅拷贝数组浅拷贝数组深拷贝对象的浅拷贝对象的深拷贝 数组浅拷贝 var arr1 = [1,2,3,4]; var arr2 = arr1; arr2[2] = 'fqniu'; console.log(arr1); // [1, 2, "fqniu", 4] console.log...
  • 数组浅拷贝和深拷贝

    2021-07-01 23:32:29
    数组浅拷贝 拷贝数组第一层 slice concat es6延展符 数组深拷贝 JSON.parse(JSON.stringify(arr)) 但会丢失react的dom节点
  • 首先解决第一个问题: & 问题一: 数组B根据数组A变化,但是不可以修改A数组 概念:1.浅拷贝: 将原对象或原数组的引用直接赋给新对象,新数组,...这里采用深拷贝的方法 js实现数组深拷贝的方法 slice, concat ...
  • JavaScript 数组对象深拷贝浅拷贝 1.浅拷贝 var data = ["11","22","33","44"]; var tempData = data; 举例:对tempData删除元素 tempData.splice(0,1),之后datatempData都是 ["22","33","44"] 1.深拷贝 var ...
  • js实现数组浅拷贝和深拷贝

    千次阅读 2019-08-19 20:24:50
    如何区分深拷贝浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。 此篇文章中也会简单阐述到栈堆,基本...
  • js数组深复制和浅复制的区别
  • let a = [1,2,3,4] let b = [...a] let [...b] = a;//这样写也行 b[2]='a' console.log(a,b)
  • 浅拷贝 ...2.数组浅拷贝一般使用 slice、concat。 3.数组浅拷贝 - 遍历 。 4.对象浅拷贝 - Object.assign()。 5.对象浅拷贝 - 扩展运算符 函数封装 //对象及数组浅拷贝函数封装 functi...
  • 我们经常会用到对一个数组或对象的拷贝...一、es5实现数组和对象的浅拷贝深拷贝 1.数组和对象浅拷贝: function shallowCopy(source){ if (typeof source !== 'object') { throw TypeError('the source must...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,835
精华内容 5,534
关键字:

js数组深拷贝和浅拷贝