深浅拷贝

作者: 感觉不错哦 | 来源:发表于2019-07-16 10:40 被阅读4次

    什么是深浅拷贝就不解释了,一般情况下我们只需要浅拷贝来操作我们的对象,但是对象内还存在对象的话就需要深拷贝了。因为浅拷贝只拷贝指针,而深拷贝可以重新申请空间并将数据复制过来,我的理解就是无限浅拷贝(^_^

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

    出现这种情况的原因很简单,因为变量b同时指向变量a的对象内存,改变a的同时b的获取内存对象也会发生改变

    浅拷贝的实现

    Object.assign

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

    展开运算符 ...

        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 a = {
        age: undefined,
        sex: Symbol('male'),
        jobs: function() {},
        name: 'lwj'
      }
    let b = JSON.parse(JSON.stringify(a))
    console.log(b) // {name: "lwj"}
    

    当然如果你会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
    

    仔细看还是能看懂的哈

    Reflect.ownKeys可以理解成Object.getOwnPropertyNames(target) concat(Object.getOwnPropertySymbols(target)、

    还是看代码吧

      var obj={}
      Object.defineProperties(obj,{
          values:{
              value:10,
              enumerable:false
          }
      })
      console.log(Object.keys(obj))//[] 空数组
      console.log(Reflect.ownKeys(obj))// values
    
    JavaScript是一门面向对象的语言,对大部分人来说这只是一句口号,很多人都不理解这句话的涵义是什么,即:为什么称JavaScript是一门面向对象的语言。

    JavaScript作为一门面向对象的语言,意味着我们不用全局定义函数去做操不同类型的值,数据类型本身可以定义方法(method)来使用值,例如,要对数组a中的元素进行排序,我们不必将a传入sort()函数,而是调用a的一个方法sort()。

        //面向过程
        function sort(arr){
        ... //将传入的数组进行排序
        return newArr
        }
        var a = [2,1,3]
        a = sort(a)
    //--------------------------------------------
    var a = [2,1,3]
    a.sort() // [1,2,3]
    

    相关文章

      网友评论

        本文标题:深浅拷贝

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