• 我对js数据类型的理解和深浅(copy)的应用场景


    一、js 数据类型

       javaScritp的数据类型有:数值类型、字符串类型、布尔类型、null、undefined、对象(数组、正则表达式、日期、函数),大致分成两种:基本数据类型和引用数据类型。

    (1)基本数据类型:数值、字符串、布尔、null、undefined (值类型)、symbol(ES6新增)

    (2)复杂(复合)数据类型:对象 (引用类型);

       基本数据类型保存在栈内存引用类型保存在堆内存中。根本原因在于保存在栈内存的必须是大小固定的数据,引用类型的大小不固定,只能保存在堆内存中,但是可以把它的地址写在栈内存中以供我们访问

      如果是基本数据类型,则按值访问,操作的就是变量保存的值;如果是引用类型的值,我们只是通过保存在变量中的引用类型的地址来操作实际对象。

    1、复制基本类型数据

    var a = 1;

    var b = a;//复制

    console.log(b)//1;

    a = 2;//改变a的值

    console.log(b)//1

    赋值的时候,在栈内存中重新开辟内存,存放变量b,所以在栈内存中分别存放着变量a、b各自的值,修改时互不影响。

    2、复制复杂类型的数据

    var color1 = ['red','green'];

    var color2 = color1;//复制

    console.log(color2)//['red','green'];

    color1.push('black') ;//改变color1的值

    console.log(color2)//['red','green','black']

    color1与color2指向堆内存中同一地址的同一对象,复制的只是引用地址

    所以,对于引用类型的复制,简单赋值无用,需要拷贝。拷贝存在两种类型:深拷贝与浅拷贝

    二、深浅拷贝的应用

    1. 浅拷贝的实现方式

      (1) Object.assign()

      可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。

      (2) lodash的clone方法

      (3)...操作符

      let obj1 = { name: 'Kobei', address:{x:100,y:100}}
      let obj2= {... obj1}
      obj1.address.x = 200;
      obj1.name = 'wade'
      console.log('obj2',obj2) // obj2 { name: 'Kobe', address: { x: 200, y: 100 } }
      复制代码

      (4) Array.prototype.concat

      let arr = [1,2,3]; let arr2 = [4,5,6];let arr3 = arr.concat(arr2)

      let arr = [1, 3, {
          username: 'kobe'
          }];
      let arr2 = arr.concat();    
      arr2[2].username = 'wade';
      console.log(arr);
      复制代码

      (5) Array.prototype.slice

      let arr = [1, 3, {2
          username: ' kobe'
          }];
      let arr3 = arr.slice();
      arr3[2].username = 'wade'
      console.log(arr); // [ 1, 3, { username: 'wade' } ]
      复制代码
    2. 深拷贝的实现方式

      (1) JSON.parse(JSON.stringify())

      可以处理数组和对象的深拷贝,但是不能处理函数和正则,因为这两者基于这两个函数处理后得到的结果不再是正则/函数

      缺点:

       1. 会忽略undefined
      
        	2. 会忽略symbol
        	3. 不能序列化函数
        	4. 不能解决循环引用的对象
      复制代码

    (2) lodash的cloneDeep函数

    (3) jQuery.extend函数

    (4) 如果所拷贝的对象含有内置对象,但是不包含函数,可以使用messagechannel,可以拷贝undefined和循环引用的对象

      ```javascript
      function structuralClone(obj) {
        return new Promise(resolve => {
          const { port1, port2 } = new MessageChannel()
          port2.onmessage = ev => resolve(ev.data)
          port1.postMessage(obj)
        })
      }
      
      var obj = {
        a: 1,
        b: {
          c: 2
        }
      }
      
      obj.b.d = obj.b
      
      // 注意该方法是异步的
      // 可以处理 undefined 和循环引用对象
      const test = async () => {
        const clone = await structuralClone(obj)
        console.log(clone)
      }
      test()

    三、 手写浅拷贝:遍历=>直接等号赋值

    // 浅拷贝
    let obj1 = {
        name : '深深地',
        arr : [1,[2,3],4],
    };
    let obj3=shallowClone(obj1)
    
    obj3.name = "春娇";
    obj3.arr[1] = [5,6,7] ; // 新旧对象还是共享同一块内存
    
    // 这是个浅拷贝的方法
    function shallowClone(source) {
        var target = {};
        for(var i in source) {
            if (source.hasOwnProperty(i)) {
                target[i] = source[i];
            }
        }
        return target;
    }
    console.log('obj1',obj1) // obj1 { name: '深深地', arr: [ 1, [ 5, 6, 7 ], 4 ] }
    console.log('obj3',obj3) // obj3 { name: '春娇', arr: [ 1, [ 5, 6, 7 ], 4 ] }
    obj.hasOwnProperty,返回值是一个布尔值,即是否是obj的属性(原型上的是false)
  • 相关阅读:
    MVC4学习-View(0)
    javascript与常用正则表达式
    uhfreader&rfid标签测试
    WebClient文件上传很方便哈
    NAudio的简单用法
    与wmi交互,调非托管代码,单元测试遇到的一些问题
    我在这里骑美团单车被交警罚了50元,这个地方不能骑共享单车大家留意了
    发邮件,美化table格式
    学习jwt的简单使用
    学习redis的基本使用
  • 原文地址:https://www.cnblogs.com/yzy521/p/14131622.html
Copyright © 2020-2023  润新知