zoukankan      html  css  js  c++  java
  • JS的赋值与深浅拷贝实例

    赋值

    • 基本类型: 传值,在栈内存中的数据发生数据变化的时候,系统会自动为新的变量分配一个新的之值在栈内存中,两个变量相互独立,互不影响的
    • 引用类型: 传址,只改变指针的指向,指向同一个对象,两个变量相互干扰
    //基本数据类型赋值
    var a = 10;
    var b = a;
    a++ ;
    console.log(a); // 11
    console.log(b); // 10
    
    //引用数据类型赋值
    let a = { name: '11' }
    let b = a
    b.name = '22'
    console.log(a.name) // 22
    console.log(b.name) // 22
    

    浅拷贝

    • 对于基本类型,浅拷贝是对值的复制,拷贝前后对象的基本数据类型互不影响
    • 对于引用类型来说,浅拷贝是对对象地址的复制, 也就是拷贝的结果是两个对象指向同一个地址,所以如果其中一个对象改变了这个地址,就会影响到另一个对象

    注意:浅拷贝只复制一层对象的属性

    实现浅拷贝方法

    方法一:Object.assign

    **语法:Object.assign(target, ...sources)   **
    ES6中拷贝对象的方法,接受的第一个参数target是拷贝后的对象,剩下的参数是要拷贝的对象sources(可以是多个)

    例1:

    let target = {};
    let source = {a:'11',b:{name:'duoduo'}};
    Object.assign(target ,source);
    console.log(target); // { a: '11', b: { name: 'duoduo' } }
    

    例2:

    let target = {};
    let source = {a:'11',b:{name:'duoduo'}};
    
    Object.assign(target ,source);
    
    source.a = '22';
    source.b.name = 'nana'
    
    console.log(source); // { a: '22', b: { name: 'nana' } }
    console.log(target); // { a: '11', b: { name: 'nana' } }
    

    Object.assign注意事项

    1. 只拷贝源对象的自身属性(不拷贝继承属性)
    2. 它不会拷贝对象不可枚举的属性
    3. undefinednull无法转成对象,它们不能作为Object.assign参数,但是可以作为源对象
    4. 属性名为Symbol 值的属性,可以被Object.assign拷贝。


    方法二:Array.prototype.slice

    实现原数组的浅拷贝

    var a = [ 1, 3, 5, { x: 1 } ];
    var b = Array.prototype.slice.call(a);
    b[0] = 2;
    console.log(a); // [ 1, 3, 5, { x: 1 } ];
    console.log(b); // [ 2, 3, 5, { x: 1 } ];
    
    // 从输出结果可以看出,浅拷贝后,数组a[0]并不会随着b[0]改变而改变
    // 说明a和b在栈内存中引用地址并不相同。
    
    var a = [ 1, 3, 5, { x: 1 } ];
    var b = Array.prototype.slice.call(a);
    b[3].x = 2;
    console.log(a); // [ 1, 3, 5, { x: 2 } ];
    console.log(b); // [ 1, 3, 5, { x: 2 } ];
    // 从输出结果可以看出,浅拷贝后,数组中对象的属性会根据修改而改变
    // 说明浅拷贝的时候拷贝的已存在对象的对象的属性引用。
    


    方法三:Array.prototype.concat

    let array = [{a: 1}, {b: 2}];
    let array1 = [{c: 3},{d: 4}];
    let array2=array.concat(array1);
    array1[0].c=123;
    console.log(array2);// [ { a: 1 }, { b: 2 }, { c: 123 }, { d: 4 } ]
    console.log(array1);// [ { c: 123 }, { d: 4 } ]
    


    方法四:...扩展运算符

    语法:var cloneObj = { ...obj };

    var a = [ 1, 3, 5, { x: 1 } ];
    var b = {...a};
    b[0] = 2;
    console.log(a); // [ 1, 3, 5, { x: 1 } ];
    console.log(b); // [ 2, 3, 5, { x: 1 } ];
    
    // 从输出结果可以看出,浅拷贝后,数组a[0]并不会随着b[0]改变而改变
    // 说明a和b在栈内存中引用地址并不相同。
    
    var a = [ 1, 3, 5, { x: 1 } ];
    var b = {...a};
    b[3].x = 2;
    console.log(a); // [ 1, 3, 5, { x: 2 } ];
    console.log(b); // [ 1, 3, 5, { x: 2 } ];
    // 从输出结果可以看出,浅拷贝后,数组中对象的属性会根据修改而改变
    // 说明浅拷贝的时候拷贝的已存在对象的对象的属性引用。
    

    其他方法:

    //浅拷贝实现
    var obj = { a:1, arr: [2,3] };
    var shallowObj = shallowCopy(obj);
    function shallowCopy(src) {
      var dst = {};
      for (var prop in src) {
        if (src.hasOwnProperty(prop)) {
          dst[prop] = src[prop];
        }
      }
      return dst;
    }
    shallowObj.arr[1] = 5;
    obj.arr[1]   // = 5
    

    深拷贝


    深拷贝开辟一个新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性

    注意:深拷贝对对象中的子对象进行递归拷贝,拷贝前后两个对象互不影响

    实现方法:

    方法一:JSON.parse(JSON.stringify())

    • JSON.stringify()是前端开发过程中比较常用的深拷贝方式。
    • 原理是把一个对象序列化成为一个JSON字符串,将对象的内容转换成字符串的形式再保存在磁盘上,再用JSON.parse()反序列化将JSON字符串变成一个新的对象
    let arr = [1, 2, {name: ' duoduo'}];
    let newarr = JSON.parse(JSON.stringify(arr));
    
    newarr[2].name = 'nana'; 
    
    console.log(newarr); // [ 1, 2, { username: 'nana' } ]
    console.log(arr);    // [ 1, 2, { username: 'duoduo' } ]
    

    JSON.stringify()实现深拷贝注意点

    1. 拷贝的对象的值中如果有函数,undefined,symbol则经过JSON.stringify()序列化后的JSON字符串中这个键值对会消失
    2. 无法拷贝不可枚举的属性,无法拷贝对象的原型链
    3. 拷贝Date引用类型会变成字符串
    4. 拷贝RegExp引用类型会变成空对象
    5. 对象中含有NaN、Infinity和-Infinity,则序列化的结果会变成null
    6. 无法拷贝对象的循环应用(即obj[key] = obj)

    方法二:jquery 的 $.extend

    var $ = require('jquery');
    var obj1 = {
        a: 1,
        b: { f: { g: 1 } },
        c: [1, 2, 3]
    };
    var obj2 = $.extend(true, {}, obj1);
    

    赋值、深拷贝、浅拷贝

    浅拷贝和拷贝****区别
    浅拷贝只复制一层对象的属性,而深拷贝则递归复制了所有层级
    fuzhi.png
    **




  • 相关阅读:
    org.apache.hadoop.security.AccessControlException: org.apache.hadoop.security.AccessControlException: Permission denied:
    linux iptables跟service 命令无效解决方法
    eclipse运行C++控制台不输出结果的解决办法
    C#操作mpp文件代码参考
    vs2010 开始执行(不调试) ctrl F5 出现任意键继续
    关于gcc、glibc和binutils模块之间的关系,以及在现有系统上如何升级的总结
    NUnit在Visual Studio 2010中的配置和使用
    【转】从CSDN的趣味题学C# 3.0
    gnome3程序图标下的文字如何改大
    使用autoconf、automake等来制作一个以源代码形式(.tar.gz)发布的软件、并可在执行configure时使用自定义参数
  • 原文地址:https://www.cnblogs.com/zhaoduoduo/p/12777383.html
Copyright © 2011-2022 走看看