美文网首页
深拷贝:简单版本

深拷贝:简单版本

作者: 黄同学2019 | 来源:发表于2020-04-24 21:23 被阅读0次

首先,先来理解一下浅拷贝和深拷贝:

  • 浅拷贝: 拷贝后端数据如果改变,原数据也被跟随改变,因为 二者的引用指向同一个地址
  • 深拷贝: 拷贝后端数据如果改变,原数据不改变,二者分别为2块不同内存地址

如果只考虑 Object 和 Array 的情况,使用递归的方式,实现简单版本的深拷贝:

 /**
  *  判断类型
  *
  * @param {*} target
  * @returns
  */
 function checkedType(target) {
  return Object.prototype.toString.call(target).slice(8, -1)
 }

/**
  * 深拷贝
  *
  * @param {*} target
  * @returns
  */
 function clone(target) {
   // 初始化变量 result 成为最终克隆数组
   let result, 
   // 判断 被拷贝数据类型
   targetType = checkedType(target);
   if (targetType === 'Array') {
      result = []
   } else if (targetType === 'Object') {
      result = {}
   } else {
      return target
   }
   // 遍历目标数据
   for (let i in target) {
     let value = target[i]
     if (['Array', 'Object'].includes(checkedType(value))) {
       // 继续遍历
       result[i] = clone(value)
     } else {
       result[i] = value
     }
   }

  return result;

 }

测试:

  • 拷贝数组测试
 // test- array
 const arr = [1,2,3]
 const arr2 = clone(arr)
 console.log('arr', arr)
 arr2.push(4)
 console.log('arr2', arr2)

 console.log('-----------')

// arr [ 1, 2, 3 ]
// arr2 [ 1, 2, 3, 4 ]
// -----------

  • 拷贝对象测试
// test-object
 const obj = {
   name: 'Tom'
 }
 const obj2 = clone(obj)
 console.log('obj', obj)
 obj2.name = 'Bom'
 console.log('obj2', obj2)

 console.log('-----------')

// obj { name: 'Tom' }
// obj2 { name: 'Bom' }
// -----------

  • 拷贝复杂类型:对象中含有数组
// test 复杂类类型

 const data = {
   name: 'Tom',
   arr: [
     {name: 'hello'}
   ]
 }

 const data2 = clone(data)
 console.log('data', data)
 data2.arr[0].name = 'word'
 console.log('data2', data2)

 console.log('-----------')

// data { name: 'Tom', arr: [ { name: 'hello' } ] }
// data2 { name: 'Tom', arr: [ { name: 'word' } ] }
// -----------

  • 数组中含有对象和数组

 const list = [1,2,3, {name: 'hey'}, [1,2,3]]
 const list2 = clone(list)

 list2[3].name = 'hi~'
 list2[4].shift()
 console.log('list', list)
 console.log('list2', list2)


// list [ 1, 2, 3, { name: 'hey' }, [ 1, 2, 3 ] ]
// list2 [ 1, 2, 3, { name: 'hi~' }, [ 2, 3 ] ]

其他深拷贝方式

最常用的就是序列化和反序列化了

JSON.parse(JSON.stringify(obj))
  • 缺点:JSON 格式只支持这 6 种值,和 js 中的类型还是有些区别,最主要的区别是数组和对象的键值需要使用双引号:
    • JSONString
    • JSONNumber
    • true/false
    • JSONArray
    • JSONObject
    • null

如果含有 Function ,返回的是 null ,因此,无法拷贝这种类型,还有 函数、引用、undefined等

当然,上面的两种递拷贝方式,本质上还都是浅拷贝,要想完整实现深拷贝,需要用到 Proxy,Reflect, 通过拦截 set 和 get 就能达到我们想要的

更多资料,参考:

const v8 = require('v8')

 const list = [1,2,3, {name: 'hey'}, [1,2,3]]
 let list2 = v8.deserialize(v8.serialize(list));

 list2[3].name = 'hi~'
 list2[4].shift()
 console.log('list', list)
 console.log('list2', list2)

// list [ 1, 2, 3, { name: 'hey' }, [ 1, 2, 3 ] ]
// list2 [ 1, 2, 3, { name: 'hi~' }, [ 2, 3 ] ]

拓展:数组中,哪些是浅拷贝?

本意就是:数组中哪些方法是返回的新数组?

  • Array.slice
  • Array.concat

MDN 描述为:

slice does not alter the original array. It returns a shallow copy of elements from the original array. Elements of the original array are copied into the returned array as follows:

相关文章

  • 深拷贝:简单版本

    首先,先来理解一下浅拷贝和深拷贝: 浅拷贝: 拷贝后端数据如果改变,原数据也被跟随改变,因为 二者的引用指向同一个...

  • js浅拷贝深拷贝

    js浅拷贝,深拷贝的简单实现 基础数据 浅拷贝 深拷贝

  • iOS - copy 与 mutableCopy

    一说到拷贝,就不得不提浅拷贝和深拷贝。 何谓浅拷贝?何谓深拷贝? 往简单的说: 浅拷贝:拷贝地址。 深拷贝:拷贝内...

  • 手写深拷贝

    手写深拷贝 深拷贝 深拷贝简单理解就是b是a的一份拷贝,且b中不存在a中对象的引用 深拷贝的实现 1.JSON序列...

  • js浅拷贝、深拷贝

    前言 本文主要简单讲一下什么是浅拷贝、什么是深拷贝、深拷贝与浅拷贝的区别,以及怎么进行深拷贝和怎么进行浅拷贝。 一...

  • java中的深拷贝和浅拷贝

    简单记录一下java中的深拷贝和浅拷贝,深拷贝和浅拷贝只是针对对象而言的. 1 深拷贝代码 2 浅拷贝代码 3 测...

  • 认识js下的浅拷贝与深拷贝

    浅拷贝与深拷贝 首先深拷贝和浅拷贝只针对像 Object, Array 这样的复杂对象的。简单来说,浅拷贝只拷贝一...

  • 深拷贝VS浅拷贝

    深拷贝VS浅拷贝 本文主要对深拷贝&浅拷贝的解释及实现做一下简单记录。 之所以会有深拷贝与浅拷贝之分,是因为不同数...

  • 深浅拷贝,面向对象,Symbol,Set,Map

    一:浅拷贝与深拷贝对象的浅拷贝:浅拷贝是对象共用的一个内存地址,对象的变化相互影响。对象的深拷贝:简单理解深拷贝是...

  • 通过jQuery中.extend()方法理解深拷贝

    所谓深拷贝和浅拷贝最大的区别就是js中有简单类型和引用类型的区分,对于简单类型不存在深拷贝和浅拷贝的区分,对于引用...

网友评论

      本文标题:深拷贝:简单版本

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