美文网首页
前端基础进阶(二): 深浅拷贝

前端基础进阶(二): 深浅拷贝

作者: 娜妹子辣辣妹子娜 | 来源:发表于2020-01-15 16:24 被阅读0次

    深拷贝与浅拷贝

    基本类型的拷贝

    先来看一段非常经典的代码

    var a = 1;
    var b = a;
    a = 200;
    console.log(a);      //200
    console.log(b);      //1
    

    我们应该知道基本类型“按值传递”,引用类型“按引用传递”,数值作为基本类型是保存在栈内存中,可以直接拿来用的,赋值是什么那么之后就一直是什么,不会受到传递元素的改变带来的影响,所以这里就不难理解上面的代码得到的值的原因了。

    引用类型的拷贝

    简单说,引用类型是生成一个指针保存的堆内存中,当给引用类型赋值时,我们写的内容是在栈内存中,也就是说我们拿到的其实是一个指针(不会直接拿到栈内存中的内容)。这个指针是指向栈内存中这个引用类型的代码。

    浅拷贝针对对象中的基本类型的值生效,但是对引用类型中还有引用类型的情况就会失效。
    所谓的深浅拷贝是相对与typeof === 'object' 而言的,数组是用堆对应保存的。
    浅拷贝:拷贝了对象的存放地址,只是指向相同而已 (只解决了第一层,对象中还有对象就不适用了)
    深拷贝:完全复制了一个独立的个体

    • 浅拷贝方法:(直接 =,Object.assign...大部分都是浅拷贝)

    =

     let arr1 = [1,3,5];
     let arr2 = arr1;
     arr1[0] = 10;
     console.log(arr2) // [10,3,5]
    
    var obj1 = {
           name: '张三'
    }
    
    var obj2 = obj1;
    obj2.name = '李四';
    
    console.log(obj1.name); // '李四'
    

    Object.assign

    var obj1 = {
           name: '张三'
    }
    
    var obj2 = Object.assign({}, obj1);
    obj2.name = '李四';
    console.log(obj1.name);  // '张三'
    

    至此,浅拷贝成功,但存在兼容性问题,比如低端的安卓机等,这个需要注意。但细心的朋友肯定会再做一个测试,如下:

    var obj1 = {
           name: '张三',
           friends: {
              name: '刘备',
              age: 33
          }
    }
    
    var obj2 = Object.assign({}, obj1);
    obj2.name = '李四';
    obj2.friends.name = '关羽';
    console.log(obj1.name);  // '张三'
    console.log(obj1.friends.name);  // '关羽'
    

    是的,到这一步,我们失败了,对象中嵌套对象时,Object.assign()只能拷贝一层,那如何解决呢?其实就要用到深拷贝的方法了:

    var obj1 = {
           name: '张三',
           friends: {
              name: '刘备',
              age: 33
          }
    }
    
    var obj2 = JSON.parse(JSON.stringify(obj1));
    obj2.name = '李四';
    obj2.friends.name = '关羽';
    console.log(obj1.name);  // '张三'
    console.log(obj1.friends.name);  // '刘备'
    
    • 深拷贝方法:
      Json.parse(Json.stringify())
    var obj1 = {
           name: '张三',
           friends: {
              name: '刘备',
              age: 33
          }
    }
    
    var obj2 = JSON.parse(JSON.stringify(obj1));
    obj2.name = '李四';
    obj2.friends.name = '关羽';
    console.log(obj1.name);  // '张三'
    console.log(obj1.friends.name);  // '刘备'
    

    $.extend
    ...运算符

     let arr = [1,3,5];
     let arr1 = [...arr];
    

    返回新数组方法 slice() 、 contat()、 map()

      let arr1 = [2,5,7];
      let arr2 = arr1.slice(0);
      let arr3 = arr1.contat();
      let arr4 = arr1.map(x => x);
      arr2[0] = 4;
     arr1[0] = 99;
    console.log(arr1,arr2) // [99,5,7]  [4,5,7] 
    

    for-in连原型链也一并复制的方法

     let arr = [1,3,5];
     let arr2 = [] ;
     for(var key in arr) {
      arr2[key] = arr[key]
    }
    

    封装方法

       /**
         * 判断对象类型
         * @param {Object} object
         * @return {String} object type
         */
        getType(object) {
            var toString = Object.prototype.toString;
            var map = {
                '[object Boolean]': 'boolean',
                '[object Number]': 'number',
                '[object String]': 'string',
                '[object Function]': 'function',
                '[object Array]': 'array',
                '[object Date]': 'date',
                '[object RegExp]': 'regExp',
                '[object Undefined]': 'undefined',
                '[object Null]': 'null',
                '[object Object]': 'object'
            };
            if (object instanceof Element) {
                return 'element';
            }
            return map[toString.call(object)];
        },
           /**
         * 对象的深度拷贝
         * @param data 需要拷贝的元数据
         * @return {any} 返回拷贝后的新数据
         */
        deepClone(data) {
            const type = this.getType(data);
            let obj;
    
            if (type === 'array') {
                obj = [];
            } else if (type === 'object') {
                obj = {};
            } else {
                //不再具有下一层次
                return data;
            }
            if (type === 'array') {
                for (let i = 0, len = data.length; i < len; i++) {
                    obj.push(this.deepClone(data[i]));
                }
            } else if (type === 'object') {
                for (let key in data) {
                    obj[key] = this.deepClone(data[key]);
                }
            }
    
            const constructor = data.constructor;
            if (constructor) {
                return Object.assign(new constructor(), obj);
            }
            return obj;
        },
    

    相关文章

      网友评论

          本文标题:前端基础进阶(二): 深浅拷贝

          本文链接:https://www.haomeiwen.com/subject/wiqovftx.html