• JavaScript深浅拷贝


    深浅拷贝

    基本类型和引用类型

    1. ECMAScript 中的变量类型分为两类:
    • 基本类型:undefined,null,布尔值(Boolean),字符串(String),数值(Number)
    • 引用类型: 统称为Object类型,细分的话,有:Object类型,Array类型,Date类型,Function类型等。
    1. 不同类型的存储方式:

    基本数据类型 保存在 栈内存,形式如下:栈内存中分别存储着变量的标识符以及变量的值。

    image

    引用类型 保存在 堆内存 中, 栈内存存储的是变量的标识符以及对象在堆内存中的存储地址,当需要访问引用类型(如对象,数组等)的值时,首先从栈中获得该对象的地址指针,然后再从对应的堆内存中取得所需的数据。

    image

    对于仅仅是复制了引用(地址),换句话说,复制了之后,原来的变量和新的变量指向同一个东西,彼此之间的操作会互相影响,为 浅拷贝。

    而如果是在堆中重新分配内存,拥有不同的地址,但是值是一样的,复制后的对象与原来的对象是完全隔离,互不影响,为 深拷贝。

    深浅拷贝 的主要区别就是:复制的是引用(地址)还是复制的是实例。

    js的复制方法

    slice和concat方法

    var a = [[1,2,3],4,5];
    var b = a.slice();
    console.log(a === b);
    a[0][0] = 6;
    console.log(a);
    console.log(b);
    

    image

    jQuery中的 extend 复制方法

    var obj = {name:'xixi',age:20,company : { name : '腾讯', address : '深圳'} };
    var obj_extend = $.extend(true,{}, obj); //extend方法,第一个参数为true,为深拷贝,为false,或者没有为浅拷贝。
    console.log(obj === obj_extend);
    obj.company.name = "ali";
    obj.name = "hei";
    console.log(obj);
    console.log(obj_extend);
    

    image

    Array 的 slice 和 concat 方法 和 jQuery 中的 extend 复制方法,他们都会复制第一层的值,对于 第一层 的值都是 深拷贝,而到 第二层 的时候 Array 的 slice 和 concat 方法就是 复制引用 ,jQuery 中的 extend 复制方法 则 取决于 你的 第一个参数, 也就是是否进行递归复制。

    JSON 对象的 parse 和 stringify

    JOSN 对象中的 stringify 可以把一个 js 对象序列化为一个 JSON 字符串,parse 可以把 JSON 字符串反序列化为一个 js 对象,这两个方法实现的是深拷贝。

    var obj = {name:'xixi',age:20,company : { name : '腾讯', address : '深圳'} };
    var obj_json = JSON.parse(JSON.stringify(obj));
    console.log(obj === obj_json);
    obj.company.name = "ali";
    obj.name = "hei";
    console.log(obj);
    console.log(obj_json);
    

    image

    但是该方法也是有局限性的:

    • 会忽略 undefined
    • 不能序列化函数
    • 不能解决循环引用的对象

    这个函数可以解决大部分问
    题,并且该函数是内置函数中处理深拷贝性能最快的。如果你的数据中含有以上三种情况下,可以使用 lodash 的深拷贝函数。

    当然,也可以利用递归自己封装深度克隆函数,

    function deepClone(origin, target){
        var target = target || {},
             toStr = Object.prototype.toString,
             arrStr = "[object Array]";
    
        for(var prop in origin){
            if(origin[prop] !== 'null' && origin.hasOwnProperty(prop)){
                if(typeof(origin[prop]) === 'object') {
                    target[prop] = toStr.call(origin[prop]) === arrStr ? [] : {};
                    deepClone(origin[prop], target[prop]);
                }else{
                    target[prop] = origin[prop];
                }
            }
        }
    }
    
  • 相关阅读:
    web应用后台开发的故事
    XML的定义、用途、以及它的发展前景和存在的问题等等
    本学期(大三下学期)学习目标
    企业级应用与互联网应用的区别?
    新能源汽车无线充电管理网站4
    新能源汽车无线充电管理网站3
    新能源汽车无线充电管理网站2
    企业级应用与互联网应用的区别
    javaee 新学期新目标
    团队项目PCP--自我评价
  • 原文地址:https://www.cnblogs.com/y-dt/p/9787506.html
Copyright © 2020-2023  润新知