JS(JavaScript)中实现深浅拷贝的几种方式(详细阅读 非常重要)。

在了解深浅拷贝之前,我们先一起来简单来了解一下,JavaScript 数据存储的方式,以及数据类型()。

JavaScript 中数据存储分为 简单数据类型复杂数据类型(引用数据类型) 其中 5 种 基本数据类型

基本数据是直接存在栈里

Boolean(布尔值 )
String (字符型) 
number (数字型,不区分浮点型和double) 
undefined (定义了变量 但未给值)
Null  (定义了变量 但赋值为 Null)

和几种常见的 引用数据类型

Object
Array
RegExp
Date
null
**// 以上几种都为 引用数据类型**

至于null 为什么是个对象,这时由于 JavaScript 早期数据在底层存储以二进制方式进行存储 如果二进制的前三位为 0
则JavaScript 会认为该数据是个对象即object所以 null 的前三位均为 0 即 null 又是基本数据类型 又是
引用数据类型

而引用数据类型我们都知道它是通过 内存地址找到对象的

JS(JavaScript)中实现深浅拷贝的几种方式(详细阅读 非常重要)。_第1张图片

接下来知道复杂数据类型是通过内存地址存储的,我们就能够明白,下一次将 obj的值赋给新对象,其实是将内存地址赋予了新对象

   const OldObj = {
      name: '张三',
      age: 18,
      hobby: ['size', 'color'],
      Around: {
        page: 10,
        size: '100KB'
      }
    }
    //将原对象赋值 新对象
    const newsObj = OldObj

    //  更改新对象的值 
    newsObj.name = '我更改了新对象的数据newsObj'
    //原对象
    console.log(OldObj);
    //新对象
    console.log(newsObj); 
  **此时会发现 我将新对象的name更改 
  但 原对象值也发生了改变,这就是因为内存地址的问题,因为它们一起引用的是同一个地址**

JS(JavaScript)中实现深浅拷贝的几种方式(详细阅读 非常重要)。_第2张图片

浅拷贝

将整个对象进行拷贝(可以理解为在栈内存中开辟了一个新的地址)

实现浅拷贝的四种式。

1:使用Object 对象原型上的 ** assign()**方法
assign(对象)
JS(JavaScript)中实现深浅拷贝的几种方式(详细阅读 非常重要)。_第3张图片

const obj = { a: 1 };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }

#方式二

利用 ES6 展开运算符,将对象展开,可以看到基本数据类型未发生更改

JS(JavaScript)中实现深浅拷贝的几种方式(详细阅读 非常重要)。_第4张图片
JS(JavaScript)中实现深浅拷贝的几种方式(详细阅读 非常重要)。_第5张图片

方式三:通过循环遍历

JS(JavaScript)中实现深浅拷贝的几种方式(详细阅读 非常重要)。_第6张图片

方式四 利用lodash 组件库调用

loadsh 官网 https://www.lodashjs.com/
JS(JavaScript)中实现深浅拷贝的几种方式(详细阅读 非常重要)。_第7张图片

引入 loadsh 

var objects = [{ 'a': 1 }, { 'b': 2 }];
 
var shallow = _.clone(objects);
console.log(shallow[0] === objects[0]);
// => true

实现深拷贝的四种方式

方式1 :也是最简单的方式 将对象通过JSON转换为字符串

    const obj = {
      uname: 'pink',
      age: 18,
      hobby: ['乒乓球', '足球'],
      family: {
        baby: '小贝贝'
      }
    }
    // 把对象转换为 JSON 字符串
    const o = JSON.parse(JSON.stringify(obj))
    //输出新对象
    console.log(o)
    // 进行数据更改 
    o.family.baby = '123'
    console.log(obj)

方式二 通过递归函数实现深拷贝

逻辑分析

// 1: indicates receiving parameters
// * 2: The type of the object passed in generates an instance object through the constructor reflection
// * 3: check that the passed object cannot be empty and is of an object type. Otherwise, return the current passed value
// * 4: iterate over every bit passed in if it can prove to be an object type
// * Check whether each attribute in an object is its own, not inherited attributes
// * 5: deep copy if object attribute is object type, shallow copy otherwise
// */
// }
// 1 : 接收参数
// // * 2 : 传递进来的对象的类型 通过constructor反射 new 出一个实例对象
// // * 3 : 判断传进来的对象不能为空 并且 是一个对象类型才能进行遍历 否则直接返回当前传进来的值
// // * 4 : 如果能遍历证明是一个 对象类型 则 遍历传进来的每一位
// // * 判断对象里的每个属性是不是自己本身的,不能是通过继承获得的属性
// // * 5 : 能够执行下来,再进行深入判断 如果对象属性 是对象类型则进行深拷贝,否则则进行浅拷贝

 **// 方法 1** 
    function deepClone (obj) {
      //  通过 constructor 反射  创建实例
      let ObjClone = new obj.constructor()
      if (obj && typeof (obj) === 'object') {
        // 遍历原来的对象
        for (key in obj) {
>          // 判断对象的属性是不是本身的属性(不能是通过原型链继承获取过来),如果是则进行下一步
          if (obj.hasOwnProperty(key)) {
            // 对象的每一位不能为空 为空无法进行拷贝
            if (obj[key] && typeof (obj[key]) === 'object') {
            // 如果是复杂数据类型 则进行递归深拷贝 否则则进行浅拷贝
              ObjClone[key] = deepClone(obj[key])
            }
            else {
            // 浅拷贝
              ObjClone[key] = obj[key]
            }
          }
        }
      }
      
      return ObjClone
    }
    // 将 拷贝的对象赋值 
    const NewsObject = deepClone(OldObj)
    // 更改 复杂数据类型数据
    NewsObject.Around.page = 1000
    // 源对象 
    console.log(OldObj);
    // 新对象
    console.log(NewsObject);
    

深拷贝第三种方式,是博主的世交好写的一篇文章,有兴趣的可以去详细阅读一下哦

https://juejin.cn/post/7085346393535201294 这是原文地址链接。

你可能感兴趣的:(前端,javascript)