美文网首页
js入门之路------深浅拷贝

js入门之路------深浅拷贝

作者: 风起长林时 | 来源:发表于2019-01-03 15:09 被阅读0次

    通常在开发中我们不希望出现这样的问题

    let a = {
      age: 1
    }
    let b = a
    a.age = 2
    console.log(b.age) // 2
    
    对于这种问题,我们就需要用到浅拷贝。

    1、使用Object.assign来实现浅拷贝

    let a = {
      age: 1
    }
    let b = Object.assign({}, a)
    a.age = 2
    console.log(b.age) // 1
    

    2、使用展开运算符 ...来实现浅拷贝

    let a = {
      age: 1
    }
    let b = { ...a }
    a.age = 2
    console.log(b.age) // 1
    
    虽然浅拷贝能解决我们日常开发中遇到的大部分问题,但是仍然还是有一些问题无法解决的。

    当我们遇到如下情况就可能需要使用到深拷贝了

    let a = {
      age: 1,
      jobs: {
        first: 'FE'
      }
    }
    let b = { ...a }
    a.jobs.first = 'native'
    console.log(b.jobs.first) // native
    

    浅拷贝只解决了第一层的问题,如果接下去的值中还有对象的话,那么就又回到最开始的话题了,两者享有相同的地址。要解决这个问题,我们就得使用深拷贝了。

    深拷贝

    通常可以通过 JSON.parse(JSON.stringify(object)) 来实现深拷贝

    let a = {
      age: 1,
      jobs: {
        first: 'FE'
      }
    }
    let b = JSON.parse(JSON.stringify(a))
    a.jobs.first = 'native'
    console.log(b.jobs.first) // FE
    

    但是该方法也是有局限性的:

    • 会忽略 undefined
    • 会忽略 symbol
    • 不能序列化函数
    • 不能解决循环引用的对象

    例如:你有这么一个循环引用对象,你会发现并不能通过该方法实现深拷贝

    let obj = {
      a: 1,
      b: {
        c: 2,
        d: 3,
      },
    }
    obj.c = obj.b
    obj.e = obj.a
    obj.b.c = obj.c
    obj.b.d = obj.b
    obj.b.e = obj.b.c
    let newObj = JSON.parse(JSON.stringify(obj))
    console.log(newObj)
    

    对于某些情况,我们可以自己实现一个深拷贝,但是这个只是简易版的,因为其实实现一个深拷贝是很困难的,需要我们考虑好多种边界情况,比如原型链如何处理、DOM 如何处理等等,相对而言,我更加推荐我其实更推荐使用 lodash 的深拷贝函数

    // 深拷贝--简易版
    function deepClone(obj) {
      function isObject(o) {
        return (typeof o === 'object' || typeof o === 'function') && o !== null
      }
    
      if (!isObject(obj)) {
        throw new Error('非对象')
      }
    
      let isArray = Array.isArray(obj)
      let newObj = isArray ? [...obj] : { ...obj }
      Reflect.ownKeys(newObj).forEach(key => {
        newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
      })
    
      return newObj
    }
    
    //例子
    let obj = {
      a: [1, 2, 3],
      b: {
        c: 2,
        d: 3
      }
    }
    let newObj = deepClone(obj)
    newObj.b.c = 1
    console.log(obj.b.c) // 2
    

    相关文章

      网友评论

          本文标题:js入门之路------深浅拷贝

          本文链接:https://www.haomeiwen.com/subject/rhifrqtx.html