深浅拷贝+异常处理

一、浅拷贝

深拷贝和浅拷贝是指在赋值一个对象时,拷贝的深度不同。

浅拷贝:把对象拷贝给一个新的对象,开发中我们经常需要复制一个对象 如果直接赋值,则复制的是地址,修改任何一个对象,另一个对象都会变化

1. 1 拷贝对象:

1.Object. assign()  

2.展开运算符  {...obj}

代码分享:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>浅拷贝-对象拷贝的两种方法</title>
</head>

<body>
  <script>
    // 浅拷贝方法

    // 1. 对象拷贝
    const obj = {
      name: '佩奇'
    }
    // 1.1 Object.assign()
    const newObj = {}
    Object.assign(newObj, obj)
    // console.log(newObj)
    console.log(newObj === obj)  // false
    newObj.name = '乔治'
    console.log(obj)
    console.log(newObj)

    // 1.2 展开运算符
    const newObj = { ...obj }
    console.log(newObj === obj)  // false
    newObj.name = '乔治'
    console.log(obj)
    console.log(newObj)


    
  </script>
</body>

</html>

1.2 拷贝数组:

1.Array.prototype.concat()  

2.展开运算符 [...arr]

代码分享:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>浅拷贝方法-数组</title>
</head>

<body>
  <script>
    // 浅拷贝方法
    // // 2. 数组拷贝
    const arr = ['佩奇', '乔治']
    // 2.1 concat 方法实现数组浅拷贝
    const arr1 = []
    const newArr = arr1.concat(arr)
    console.log(newArr)
    newArr[1] = '猪爸爸'
    console.log(arr)
    console.log(newArr)

    // 2.2 展开运算符
    const newArr = [...arr]
    console.log(newArr)
    newArr[1] = '猪爸爸'
    console.log(arr)
    console.log(newArr)

  </script>
</body>

</html>

1.3 浅拷贝的问题:

浅拷贝只会拷贝对象的第一层属性,如果这些属性是对象,则不会对这些对象进行拷贝,而是直接复制对象的引用。这意味着,对于浅拷贝后的对象,如果原对象的属性值发生了变化,浅拷贝后的对象的属性值也会跟着发生变化。

代码分享:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>浅拷贝存在的问题</title>
</head>

<body>
  <script>
    // 浅拷贝方法
    // 3. 浅拷贝的问题如果遇到多层拷贝还是会影响原来的对象
    const obj = {
      name: '佩奇',
      family: {
        father: '猪爸爸'
      }
    }
    const newObj = { ...obj }
    // console.log(newObj)
    newObj.family.father = 'dad'
    console.log(newObj)
    console.log(obj)
  </script>
</body>

</html>

效果展示:

 

二、深拷贝

深拷贝:拷贝多层,不再拷贝地址

实现深拷贝三种方式?

(1)利用JSON序列化(常用)

(2)利用js库 lodash里面的  _.cloneDeep() (常用)

(3)自己利用递归函数书写深拷贝(理解)

在进行深拷贝时,会拷贝所有的属性,并且如果这些属性是对象,也会对这些对象进行深拷贝,直到最底层的基本数据类型为止。这意味着,对于深拷贝后的对象,即使原对象的属性值发生了变化,深拷贝后的对象的属性值也不会受到影响。在开发中,一般如果我想要使用这个对象内的数据,但是不想修改原本的对象内的数据内容时,使用深浅拷贝来复制数据,并对新的对象内的数据进行操作。

2.1 通过 JSON 序列化实现

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>深拷贝-JSON序列化</title>
</head>

<body>
  <script>
    // 深拷贝实现方式一:JSON序列化(常用的方式)
    // const obj = {
    //   name: '佩奇',
    //   family: {
    //     father: '猪爸爸'
    //   },
    //   hobby: ['跳泥坑', '唱歌']
    // }

    // // console.log(JSON.stringify(obj))
    // // console.log(JSON.parse(JSON.stringify(obj)))
    // const newObj = JSON.parse(JSON.stringify(obj))
    // console.log(newObj === obj)  // false
    // newObj.family.father = 'dad'
    // console.log(obj)
    // console.log(newObj)

    // 注意事项:JSON.stringify序列化的时候会忽略 function undefined
    const obj = {
      name: '佩奇',
      love: undefined,
      family: {
        father: '猪爸爸'
      },
      hobby: ['跳泥坑', '唱歌'],
      sayHi() {
        console.log('我会唱歌')
      }
    }
    const newObj = JSON.parse(JSON.stringify(obj))
    console.log(newObj)
  </script>
</body>

</html>

2.2 lodash库 实现     

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>深拷贝-lodash库实现</title>
</head>

<body>
  <!-- 引入lodash库 -->
  <script src="./js/lodash.min.js"></script>
  <script>
    const obj = {
      name: '佩奇',
      love: undefined,
      family: {
        father: '猪爸爸'
      },
      hobby: ['跳泥坑', '唱歌'],
      sayHi() {
        console.log('我会唱歌')
      }
    }
    // lodash 库实现
    const newObj = _.cloneDeep(obj)
    // console.log(newObj)
    newObj.family.father = 'dad'
    console.log(obj)
    console.log(newObj)

  </script>
</body>

</html>

2.3 通过递归实现

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>深拷贝-递归实现深拷贝</title>
</head>

<body>
  <script>
    // 递归实现深拷贝 - 简版实现对象和数组的拷贝
    const obj = {
      name: '佩奇',
      family: {
        father: '猪爸爸'
      },
      hobby: ['跳泥坑', '唱歌'],
    }

    // 封装深拷贝函数 cloneDeep()
    function cloneDeep(oldObj) {
      // 先判断拷贝的是数组还是对象
      const newObj = Array.isArray(oldObj) ? [] : {}

      // 遍历拷贝属性和值
      for (let k in oldObj) {
        // console.log(k)  // k 是属性
        // console.log(oldObj[k])  // oldObj[k] 是属性值
        // 把旧对象的值给新对象的属性
        if (typeof oldObj[k] === 'object') {
          // 如果属性值是引用数据类型,则需要递归再次拷贝
          newObj[k] = cloneDeep(oldObj[k])

        } else {
          // 否则属性值是基本数据类型,则直接赋值即可
          newObj[k] = oldObj[k]
        }
      }

      // 返回新对象
      return newObj
    }
    const newObj = cloneDeep(obj)
    newObj.family.father = 'dad'
    console.log(newObj)
    console.log(obj) 
  </script>
</body>

</html>

三、异常处理

3.1 throw 抛异常

异常处理是指预估代码执行过程中可能发生的错误,然后最大程度的避免错误的发生导致整个程序无法继续运行

总结:

1. throw 抛出异常信息,程序也会终止执行

2. throw 后面跟的是错误提示信息

3. Error 对象配合 throw 使用,能够设置更详细的错误信息

代码分享:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>异常处理-throw抛出异常</title>
</head>

<body>
  <script>
    // 异常处理 - throw抛出异常
    function count(x, y) {
      if (!x || !y) {
        // throw '请输入参数'
        throw new Error('函数的参数不能为空')
        console.log(111)
      }
      return x + y
    }
    count()
  </script>
</body>

</html>

效果展示:

3.2 try /catch 捕获异常 

我们想要测试某些代码是否有异常,可以通过try / catch 捕获错误信息(浏览器提供的错误信息)   try 试试   catch 拦住  finally  最后

说明: 1. 将预估可能发生错误的代码写在 try 代码段中 2. 如果 try 代码段中出现错误后,会执行 catch 代码段,并截获到错误信息 3. finally  不管是否有错误,都会执行

代码分享:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>try/catch 捕获错误信息</title>
</head>

<body>
  <p>我是测试文字</p>
  <script>
    // try/catch 捕获错误信息
    try {
      // 要写测试的代码可能出现错误的代码
      const p = document.querySelector('.p')
      p.style.color = 'red'
    } catch (error) {
      // 如果try里面的代码出现错误,则进入catch , 参数 error 是错误信息
      // console.log(error)
      throw error
    } finally {
      // 不管代码是否有错误都会执行
      console.log('不管代码是否有错误都会执行')
    }

  </script>
</body>

</html>

效果展示:

3.3 debugger 

debugger 语句调用调试功能,例如设置断点

代码分享:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>异常处理-debugger</title>
</head>

<body>
  <script>
    // 异常处理 -debugger
    const obj = {
      name: '佩奇',
      family: {
        father: '猪爸爸'
      },
      hobby: ['跳泥坑', '唱歌'],
    }
    // 封装深拷贝函数 cloneDeep()
    function cloneDeep(oldObj) {
      const newObj = Array.isArray(oldObj) ? [] : {}
      debugger9
      for (let k in oldObj) {
        if (typeof oldObj[k] === 'object') {
          newObj[k] = cloneDeep(oldObj[k])

        } else {
          newObj[k] = oldObj[k]
        }
      }
      return newObj
    }
    const newObj = cloneDeep(obj)
    newObj.family.father = 'dad'
    console.log(newObj)
    console.log(obj)



  </script>
</body>

</html>

效果展示:

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值