js深度拷贝

一般实现方式有两种:

  1. JSON.parse(JSON.stringify(obj)),用法说明参考developer.mozilla.org/zh-CN/docs/…

    注意点,不可枚举undefined函数symbol是不能stringify的,另外循环引用会报错,如下:

可以通过一下方式处理: (使用 json.stringify的第二个参数)

var cache = []
JSON.stringify(json, (key, value) => {
    if (typeof value === 'object' && value !== null) {
        if (cache.indexOf(value) !== -1) {
            return // 或者 return undefined
        }
        cache.push(value)
    }
    return value;
})
复制代码
  1. 直接实现:

    从上面的stringify的用法,就会发现弊端,如无法拷贝函数引用等等以及循环引用的bug,不过处理循环无污染的方式是用一个数组记录(污染的方式是对每一个对象添加一个__used的属性标记改对象已被使用,无需再调用赋值),具体代码如下:

function deepClone(obj) {
    const rootObj = {} // 记录新的对象
    const cache = [obj] // 引用对象数组
    const cacheNewValues = [rootObj] // 记录对应引用的新值

    const assign = (innerObj) => {
      const newObj = innerObj === obj ? rootObj : {}
      Object.keys(innerObj).forEach(key => {
        const value = innerObj[key]
        const index = cache.indexOf(value)
        // 未缓存
        if(index === -1) {
          const type = Object.prototype.toString.call(value)
          if (typeof type === 'object') {
            newObj[key] = assign(value)
            // 记录引用的对象以及对应引用的新值
            cache.push(value)
            cacheNewValues.push(newObj[key])
          } else {
            newObj[key] = value
          }
        } else {
          // 已缓存,取对应缓存的新值
          newObj[key] = cacheNewValues[index]
        }
      })
      
      return newObj
    }

    return assign(obj);
};
复制代码

运行如下:

思考: 栈溢出了呢? 下次更新这个问题

转载于:https://juejin.im/post/5bcc9b2e518825777c39280c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值