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

    ECMAScript中的数据类型可以分为两种:

    基本类型:Undefined, Null, Boolean, String, Number, Symbol

    引用类型:Object, Array, Function, RegExp等

    不同类型的存储方式:

    基本类型:基本类型值在内存中占据固定大小,保存在栈内存中

    引用类型:引用类型的值是对象,保存在堆内存中,而栈内存存储的是对象的变量标识符以及对象在堆内存中的存储地址

    不同类型的复制方式:

    基本类型:从一个变量向另外一个新变量复制基本类型的值,会创建这个值的一个副本,并将该副本复制给新变量。

    let foo = 1;
    let bar = foo;
    console.log(foo === bar);  // => true
    // 修改foo的值并不会改变bar的值
    foo = 10;
    console.log(foo);  // => 10     
    console.log(bar);  // => 1

    引用类型:从一个变量向另外一个新变量复制引用类型的值,实际上复制的是指针,最终两个变量都指向同一个对象。

    let foo = {
           name: 'deeper',
           age: 10
    };
    let bar = foo;
    console.log(foo === bar);  // => true
    
    //修改foo的值会影响bar的值
    foo.age = 20;
    console.log(foo);   // => {name: 'deeper', age: 20}
    console.log(bar);   // => {name: 'deeper', age: 20}

    深拷贝 & 浅拷贝

    浅拷贝:仅仅是复制了引用,彼此之间的操作会相互影响;

    深拷贝:在堆中重新分配内存,不同的地址,相同的值,互不影响;

    深拷贝的实现:

    一:利用递归实现对对象或数组的深拷贝

    function deepCopy(obj) {
       if(!obj || typeof obj !== 'object') {
            throw new Error('error arguments');
        }
        const targetObj = Array.isArray(obj) ? [] : {};
        for(let key in obj) {
             if(obj.hasOwnProperty(key)) {
                if(obj[key] && typeof obj[key] === 'object') {
                     targetObj[key] = deepCopy(obj[key]);
                } else {
                     targetObj[key] = obj[key];
                }
             } 
        }
        return targetObj;
    }    

    原生JavaScript中提供的一些方法

    1、Array.prototype.slice(start, end):从已有的数组中返回选定的元素。

    let a = [1, 2, 3, 4];
    let b = a.slice();
    console.log(a === b); // -> false
    
    a[0] = 5;
    console.log(a); // -> [5, 2, 3, 4]
    console.log(b); // -> [1, 2, 3, 4]

    but :

    let a = [[1, 2], 3, 4];
    let b = a.slice();
    console.log(a === b); // -> false
    
    a[0][0] = 0;
    console.log(a); // -> [[0, 2], 3, 4]
    console.log(b); // -> [[0, 2], 3, 4]

    2、Array.prototype.concat()

    let a = [1, 2, 3, 4];
    let b = a.concat();
    console.log(a === b); // -> false
    
    a[0] = 5;
    console.log(a); // -> [5, 2, 3, 4]
    console.log(b); // -> [1, 2, 3, 4]

    but:

    let a = [[1, 2], 3, 4];
    let b = a.concat();
    console.log(a === b); // -> false
    
    a[0][0] = 0;
    console.log(a); // -> [[0, 2], 3, 4]
    console.log(b); // -> [[0, 2], 3, 4]

    由此可见Array的slice和concat方法并不是真正的深拷贝,对于Array的第一维元素是深拷贝,而第二维的slice和concat方法是复制引用,所以,Array的slice和concat方法都是浅拷贝。

    3、JSON.stringify()和JSON.parse()

    1. JSON.stringify():把一个js对象序列化为一个JSON字符串
    2. JSON.parse():把JSON字符串反序列化为一个js对象
    let obj = {
      name: 'deeper',
      age: 20,
      friend: {
        name: 'lee',
        age: 19
      }
    };
    let copyObj = JSON.parse(JSON.stringify(obj));
    obj.name = 'Sandman';
    obj.friend.name = 'Jerry';
    console.log(obj);
    // -> {name: "Sandman", age: 20, friend: {age: 19,name: 'Jerry'}}
    console.log(copyObj);
    // -> {name: "deeper", age: 20, friend: {age: 19,name: 'lee'}}

    JSON.parse()和JSON.stringify()是完全的深拷贝

    深拷贝的实现也可以这样:

    export const cloneObject = (source?: any) => {
        const json = JSON.stringify(source);
        const result = JSON.parse(json);
        result.__proto__ = source.__proto__;
        return result;
    }; 
  • 相关阅读:
    wp7 db
    wp7 webpair
    wp7 弹出动画
    wp7 执行独立存储任务
    黑马程序员第二阶段JAVA网络编程第24天
    黑马程序员第二阶段图形用户界面第22天(1)
    黑马程序员第三阶段Java基础加强第26天
    黑马程序员第三阶段Java基础加强第25天
    黑马程序员第二阶段Java高级IO第21天
    黑马程序员第二阶段JAVA网络编程第23天
  • 原文地址:https://www.cnblogs.com/xuepei/p/9067562.html
Copyright © 2011-2022 走看看