(知识点)化学实验基本内存的实现方式与图解

  目录一.数据类型二.浅拷贝与深拷贝三.赋值和浅拷贝的区别四.浅拷贝的实现方式五.深拷贝的实现方式一.数据类型

  数据分为基本数据类型(String, Number, Boolean, Null, Undefined,Symbol)和对象数据类型。

  基本数据类型:

  访问:基本数据类型的值是按值访问的。

  存储:基本类型的变量是存放在栈内存(Stack)里的。

  图解 : 栈内存中包括了变量的标示符和变量的值。

  引用数据类型的特点:存储的是该对象在栈中引用,真实的数据存放在堆内存里

  引用数据类型在栈中储存了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获取实体。

  访问:引用类型的值是按引用访问的。

  存储:引用类型的值是保存在堆内存(Heap)中的对象(Object)。

  图解:

  栈内存中包含了变量的标示符和指向堆内存中该对象的指针

  堆内存中包含了对象的内容

  image

  JavaScript 不能直接操作对象的内存空间(堆内存)一.浅拷贝与深拷贝

  深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的。

  深拷贝和浅拷贝的示意图大致如下:

  image

  浅拷贝只复制指向某个对象的指针,而不是复制对象本身 新旧对象还是共享同一块内存。

  但深拷贝会另外创造一个一摸一样的对象, 新对象跟原对象不共享内存,修改新对象不会改到原对象。三.赋值和浅拷贝的区别

   // 对象赋值

     var obj1 = {
        'name' : 'zhangsan',
        'age' :  '18',
        'language' : [1,[2,3],[4,5]],
    };
    var obj2 = obj1;
    obj2.name = "lisi";
    obj2.language[1] = ["二","三"];
    console.log('obj1',obj1)
    console.log('obj2',obj2)

  image

   // 浅拷贝

     var obj1 = {
        'name' : 'zhangsan',
        'age' :  '18',
        'language' : [1,[2,3],[4,5]],
    };
     var obj3 = shallowCopy(obj1);
     obj3.name = "lisi";
     obj3.language[1] = ["二","三"];
     function shallowCopy(src) {
        var dst = {};
        for (var prop in src) {
            if (src.hasOwnProperty(prop)) {
                dst[prop] = src[prop];
            }
        }
        return dst;
    }
    console.log('obj1',obj1)
    console.log('obj3',obj3)

  image

  上面例子中,obj1是原始数据,obj2是赋值操作得到,而obj3浅拷贝得到。我们可以很清晰看到对原始数据的影响,具体请看下表:

  image

  四.浅拷贝的实现方式

  1.Object.assign()

  Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象js array slice 浅拷贝,然后返回目标对象。但是 Object.assign()进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。

  js深拷贝和浅拷贝_js array slice 浅拷贝_js深拷贝和浅拷贝的区别

   var obj = { a: {a: "xxxc", b: 19} };

    var initalObj = Object.assign({}, obj);
    initalObj.a.a = "wewd";
    console.log(obj.a.a); //wewd

  注意:当object只有一层的时候js array slice 浅拷贝,是深拷贝

   let obj = {

        username: 'jsx'
        };
    let obj2 = Object.assign({},obj);
    obj2.username = 'wawa';
    console.log(obj);//{username: "jsx"}

  2.Array.prototype.concat()

   let arr = [1, 3, {

        username: 'kobe'
        }];
    let arr2=arr.concat();    
    arr2[2].username = 'wade';
    console.log(arr);

  修改新对象会改到原对象:

  example

  3.Array.prototype.slice()

   let arr = [1, 3, {

        username: ' kobe'
        }];
    let arr3 = arr.slice();
    arr3[2].username = 'wade'
    console.log(arr);

  修改新对象会改到原对象:

  image

  Array的slice和concat方法不修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。

  原数组的元素会按照下述规则拷贝:

   let arr = [1, 3, {

        username: ' kobe'
        }];
    let arr3 = arr.slice();
    arr3[1] = 2
    console.log(arr,arr3);

  image

  五.深拷贝的实现方式

  1.递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝

   var deepCopy = function(obj) {

        if (typeof obj !== 'object') return obj //判断不是object就直接返回
        var newObj = (Object.prototype.toString.call(obj) === '[object Array]') ? [] : {} //判断复制的目标是数组还是对象
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                newObj[key] = (typeof obj[key] !== 'object') ? obj[key]: deepCopy(obj[key]) // 如果值是对象,就递归一下。 如果不是,就直接赋值
            }
        }
        return newObj
    }

  就这么简单。

  js深拷贝和浅拷贝_js深拷贝和浅拷贝的区别_js array slice 浅拷贝

  类似的方法都是挺雷同的

   function deepClone(source){

      const targetObj = source.constructor === Array ? [] : {}; // 判断复制的目标是数组还是对象
      for(let keys in source){ // 遍历目标
        if(source.hasOwnProperty(keys)){
          if(source[keys] && typeof source[keys] === 'object'){ // 如果值是对象,就递归一下
            targetObj[keys] = source[keys].constructor === Array ? [] : {};
            targetObj[keys] = deepClone(source[keys]);
          }else{ // 如果不是,就直接赋值
            targetObj[keys] = source[keys];
          }
        }
      }
      return targetObj;
    }  
    /*原理都一样*/
    var  deepClone=function(source) {
      if (!source && typeof source !== 'object') {
        throw new Error('error arguments', 'deepClone')
      }
      const targetObj = source.constructor === Array ? [] : {}
      Object.keys(source).forEach(keys => {
        if (source[keys] && typeof source[keys] === 'object') {
          targetObj[keys] = deepClone(source[keys])
        } else {
          targetObj[keys] = source[keys]
        }
      })
      return targetObj
    }

  2.除此之外还有 函数库 lodash

  该函数库也有提供_.cloneDeep用来做 Deep Copy

   var _ = require('lodash');

    var obj1 = {
        a: 1,
        b: { f: { g: 1 } },
        c: [1, 2, 3]
    };
    var obj2 = _.cloneDeep(obj1);
    console.log(obj1.b.f === obj2.b.f);
    // false

  JSON.parse(JSON.stringfify(obj))

  3.JSON.parse(JSON.stringfify(obj))

  原理:

  用JSON.stringify将对象转成JSON字符串,

  再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。

  可以实现数组或对象深拷贝,但不能处理函数

  因为JSON.stringify() 方法是将一个JavaScript值(对象或者数组)转换为一个 JSON字符串,不能接受函数

  可以自行试验 就不做图例了,太懒了

文章由官网发布,如若转载,请注明出处:https://www.veimoz.com/1477
0 评论
334

发表评论

!