zoukankan      html  css  js  c++  java
  • javascript实现引用数据类型的深拷贝和浅拷贝详解

    关于引用类型值的详解,请看另一篇随笔 https://www.cnblogs.com/jinbang/p/10346584.html

    深拷贝和浅拷贝,也就是引用数据类型栈和堆的知识点。深浅拷贝的原型都是Object,深拷贝指向的堆内存不一样,浅拷贝指向的堆内存一样):
    如何区分深拷贝与浅拷贝,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B没有发生变化,说明是深拷贝。如果B也跟着发生了变化,说明是浅拷贝。
          let obj = { name: "jin", arr: ["red","blue","black"]};
          let obj1 = {};
          Object.defineProperties(obj1, Object.getOwnPropertyDescriptors(obj)); // 深拷贝
          Object.assign(obj1, obj); // 深拷贝
          obj1 = JSON.parse(JSON.stringify(obj)); // 深拷贝
          obj1 = deepCopy(obj); // 使用到深拷贝函数
          obj1 = obj; // 浅拷贝
          obj1 = Object.assign(obj); // 浅拷贝

    下面是deepCopy()深拷贝函数,其中使用到了判断变量的类型函数

          // 判断变量的类型
          function getType(obj){
            let str = Object.prototype.toString.call(obj); // 检测基本类型值,引用类型值的类型
            let map = {
              '[object Boolean]': 'boolean',
              '[object Number]': 'number',
              '[object String]': 'string',
              '[object Function]': 'function',
              '[object Array]': 'array',
              '[object Date]': 'date',
              '[object RegExp]': 'regExp',
              '[object Undefined]': 'unfefined',
              '[object Null]': 'null',
              '[object Object]': 'object'
            };
            if(obj instanceof Element){
              return 'element';
            }
            return map[str];
          }
    
          // 深拷贝函数
          function deepCopy(p){
            let obj;
            let str = getType(p);
            if(str === 'array'){
              obj = [];
              for(let i=0;i<p.length;i++){
                // obj.push(p[i]); // 不能这样写,因为会把array的堆内存也会复制过去
                obj.push(arguments.callee(p[i])); //回调自己
              }
            }else if(str === 'object'){
              obj = {};
              for(let i in p){
                // obj[i] = p[i]; // 不能这样写,因为会把object的堆内存也会复制过去
                obj[i] = arguments.callee(p[i]); //回调自己
              }
            } else {
              return p;
            }
            return obj;
          }

    需要特别注意的是,使用JSON.parse(JSON.stringify(x))不是一个很好的选择,也算是它们的坑吧:

    对象是由构造函数生成的:会丢弃对象的constructor,因为JSON.stringify()只能序列化对象的可枚举的自有属性
    时间对象:变成字符串
    RegExp,Error对象:变成空对象
    函数,undefined:会被丢失
    NaN,Infinity和-Infinity:变成null
    function Person(name){
          this.name = name;
        }
        var person = new Person('liai');
        
        var test = {
          name: 'jin',
          person: person, //对象是由构造函数生成的:会丢弃对象的constructor
          date: new Date(), //序列化后返回是字符串,不是时间对象
          regexp: new RegExp('\w+'), //序列化后返回空对象:{}
          err: new Error(),  //序列化后返回空对象:{}
          fun: function(){}, //序列化后会丢失
          undef: undefined, //序列化后会丢失
          nun: NaN, //序列化后返回null
        };
        console.log(test);
        console.log(JSON.parse(JSON.stringify(test)));
  • 相关阅读:
    触动心灵的话语
    join和os.path.join 的用法
    os.path.join 的用法
    Python中函数的定义必须在调用的前面
    矩阵和数组的区别
    Object detection with deep learning and OpenCV
    YOLO Object Detection with OpenCV
    Python-OpenCV中VideoCapture类的使用
    Object Detection: Face Detection using Haar Cascades
    有关目标检测的文章
  • 原文地址:https://www.cnblogs.com/jinbang/p/10346649.html
Copyright © 2011-2022 走看看