资讯专栏INFORMATION COLUMN

JS中深拷贝与浅拷贝

ranwu / 2112人阅读

摘要:地址传递引用类型则是地址传递,将存放在栈内存中的地址赋值给接收的变量。即对象的浅拷贝会对主对象进行拷贝,但不会复制主对象里面的对象。

相关知识点

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

基本类型值指的是简单的数据段,包括es6里面新增的一共是有6种,具体如下:number、string、boolean、null、undefined、symbol。

引用类型值指那些可能由多个值构成的对象,只有一种如下:object。
在将一个值赋给变量时,解析器必须确定这个值是基本类型值还是引用类型值。

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

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

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

基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值。
引用类型的值是保存在内存中的对象。JavaScript 不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。 在操作对象时, 实际上是在操作对象的引用而不是实际的对象。

基本类型与引用类型最大的区别实际就是 传值与传址 的区别

值传递:基本类型采用的是值传递。
地址传递:引用类型则是地址传递,将存放在栈内存中的地址赋值给接收的变量。

浅拷贝
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。”里面的对象“会在原来的对象和它的副本之间共享。

基本数据类型Number(赋值操作)

let a=1;
let b=a;
    b           //1
    b=2;
    b          //2
    a          //1

数组

let arr1 = [1,2,3];
let arr2 = arr1;
    arr2         //[1,2,3]
    arr2.push(4);
    arr2         //[1,2,3,4]
    arr1         //[1,2,3,4]

首先栈内存arr1会指向堆内存里的数组,栈内存的arr1保存的是数组的引用,也就相当于内存地址,arr2=arr1,会把arr1的引用赋给arr2,所以arr2也有了数组的引用,此时arr1和arr2指向的是同一个数组,因此一个数组的改变会影响另一个数组的值。

对象

let obj1={count:1,name:"grace",age:1};
let obj2 = obj1;
    obj2        //{count:1,name:"grace",age:1}
    obj2.count=2;
    obj1        //{count:2,name:"grace",age:1}
    obj2        //{count:2,name:"grace",age:1}

综上所述,如果是基本数据类型,直接进行赋值操作,这样就相当于在栈内存中重新开辟了一个新的空间把值传递过去;如果是引用类型的值传递,进行的就是浅拷贝,浅拷贝赋值的只是对象的引用,如上述obj2=obj1,实际上传递的只是obj1的内存地址,所以obj2和obj1指向的是同一个内存地址,所以这个内存地址中值的改变对obj1和obj2都有影响。

深拷贝
深拷贝不仅将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深复制的方法递归复制到新对象上,所以对一个对象的修改并不会影响另一个对象。

数组

法一:for循环

let arr1 = [1,2,3];
let arr2 = copyArr(arr1);
function copyArr(arr){
    let res=[];
    for(let i=0,length=arr.length;i

法二: slice

用数组自身的方法,slice、concat方法在运行后会返回新的数组

let arr1 = [1,2,3];
let arr2 = arr1.slice(0);

法三: concat

let arr1 = [1,2,3];
let arr2 = arr1.concat();

法四:扩展运算符

let arr1 = [1,2,3];
let [...arr2] = arr1;

法五:Array.from

如果参数是一个真正的数组,Array.from会返回一个一模一样的新数组

let arr1 = [1,2,3];
let arr2 = Array.from(arr1);

对象

法一:for循环

let obj1={count:1,name:"grace",age:1};
let obj2 = copyObj(obj){
    let res = {};
    for(let key in obj){
      res[key]=obj[key];
    }
    return res;

}

法二:利用JSON

let obj1={count:1,name:"grace",age:1};
let obj2 = JSON.parse(JSON.stringify(obj1));

//使用JSON比较简单,但是JSON的深拷贝方式会忽略函数对象和原型对象(有待考证)

法三:扩展运算符

 let obj1={count:1,name:"grace",age:1};
 let {...obj2} = obj1;

合成版,可以实现数组和对象的深拷贝
 function deepCopy(obj){
        let result = Array.isArray(obj)?[]:{};  
        if(obj && typeof obj === "object"){ 
            for(let key in obj){
                if(obj.hasOwnProperty(key)){
                    if(obj[key]&&typeof obj[key]==="object"){
                        result[key]=deepCopy(obj[key]);
                    }else{
                        result[key]=obj[key];
                    }
                }
            }
        }
        return result;
    }

注意:ES6新增了Object.assign() 方法

第一个参数是目标对象,之后还可以跟一个或多个源对象。它会遍历一个或多个源对象可枚举的自有键并把它们复制到目标对象,最后返回目标对象
assign是使用=操作符来赋值,

Object.assign() 只是一级属性复制,比浅拷贝多深拷贝了一层而已。用的时候,还是要注意这个问题的

作者:优雅1217
来源:CSDN
原文:https://blog.csdn.net/baidu_3...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/102430.html

相关文章

  • js中深拷贝与浅拷贝(堆内存、栈内存的关系)

    摘要:而堆内存主要负责像对象这种变量类型的存储,如下图引用类型中复制浅拷贝的只是栈内存中的指针,指向同一个堆内存的对象如何实现深拷贝最简单的方法就是与方法 浅拷贝只会在引用类型中出现 基本数据类型有哪些,number,string,boolean,null,undefined,symbol以及未来ES10新增的BigInt(任意精度整数)七类。 引用数据类型(Object类)有常规名值对的无...

    AlienZHOU 评论0 收藏0
  • 深入JavaScript中深拷贝和浅拷贝

    摘要:深拷贝和浅拷贝问题的本质还是不同数据类型的存储方式差异,尤其是引用数据类型的特殊。 深拷贝和浅拷贝问题的本质还是不同数据类型的存储方式差异,尤其是引用数据类型的特殊。showImg(https://segmentfault.com/img/bVbb8XH?w=1058&h=409); 现分别对赋值、浅拷贝、深拷贝做深入研究: 1.赋值 原理:直接将对象指针直接赋值给另一个变量 代码: ...

    TalkingData 评论0 收藏0
  • 浅谈JavaScript 中深拷贝实现的方法

    摘要:相信人很多学习的过程中都踩了深拷贝和浅拷贝的坑,深拷贝和浅拷贝的区别我就不再赘述了,今天我来写一下我自己实现深拷贝的各种方法。中的深拷贝也是用类似方法实现。 相信人很多学习js的过程中都踩了深拷贝和浅拷贝的坑,深拷贝和浅拷贝的区别我就不再赘述了,今天我来写一下我自己实现深拷贝的各种方法。 比较简单的拷贝方式可以借用浏览器的Json对象去实现,先把对象转化为json字符串,在解析回对...

    Vicky 评论0 收藏0
  • JS中的深拷贝与浅拷贝

    摘要:中的深拷贝与浅拷贝说到深浅拷贝的时候就不得不说一下中的变量类型了基本类型按值存放在栈内存中的简单数据段可以直接访问引用类型存放在堆内存中的对象变量保存的是一个指向存放数据位置的指针访问引用类型的值时首先从栈中获取到存放该数据位置的指针然后再 JS中的深拷贝与浅拷贝 说到深浅拷贝的时候就不得不说一下JS中的变量类型了: 基本类型: undefined、null、boolean、numb...

    ARGUS 评论0 收藏0
  • JS每日一题:深拷贝与浅拷贝的区别?如何实现一个深拷贝

    摘要:期深拷贝与浅拷贝的区别如何实现一个深拷贝在回答这个问题前,我们先来回顾一下中两大数据类型基本类型引用类型基本类型基本类型就是值类型存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配引用类型引用类型存放在堆内存中的对象,变量实际保 20190311期 深拷贝与浅拷贝的区别?如何实现一个深拷贝 在回答这个问题前,我们先来回顾一下JS中两大数据类型 基本类型 Undefined...

    MiracleWong 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<