• js---封装浅拷贝和深拷贝


    一、前置知识

    基本数据类型和引用数据类型的存储方式

    二、概念

    浅拷贝:只能拷贝最外面一层的数据,基本类型的数据直接拷贝值;引用数据类型只拷贝数据的引用(地址),拷贝的引用类型数据与源数据指向同一个堆内存空间,当拷贝的引用类型数据或者源数据其中一方修改时,双方会被同时修改。

    深拷贝:拷贝多层数据;每一层的基本数据类型和引用数据类型的数据都会复制一份,其中复制引用数据类型的数据是具有新的内存空间,拷贝的所有数据与源数据互不影响。

    三、浅拷贝

    1.推荐使用es6的 Object.assgin() 实现浅拷贝

    mdn地址:

    Object.assign() - JavaScript | MDN

    2.自己封装浅拷贝函数

    1. <script>
    2. // -----------------------利用for in 实现对象的浅拷贝----------------------
    3. // 1.拷贝的数据源
    4. const obj = {
    5. name: "hsq",
    6. age: 18,
    7. color: ["red", "blue", "green"],
    8. children: {
    9. name: 'xxx',
    10. age: 1
    11. },
    12. say: function () {
    13. console.log(this);
    14. }
    15. }
    16. //2.调用浅拷贝函数将数据源obj进行浅拷贝并返回拷贝好的对象,使用testObj常量接收
    17. const testObj = simpleObjClone({}, obj)
    18. //3.修改数据源对象中的引用类型属性color数组的第一项
    19. obj.color[0] = 'hhh'
    20. //4.打印通过浅拷贝成功的对象的引用类型属性color数组的第一项,发现浅拷贝的数据发生更改
    21. console.log(testObj.color[0]);//hhh
    22. //浅拷贝函数
    23. function simpleObjClone(resultObj, Obj) {
    24. //两个参数必须存在而且要求参数的类型相同,类型同为数组或者对象
    25. const verify1 = resultObj && isArray(resultObj) && Obj && isArray(Obj)
    26. const verify2 = resultObj && isObject(resultObj) && Obj && isObject(Obj)
    27. if (verify1 || verify2) {
    28. // 利用for in循环对象或者数组的每一项并复制给resultObj参数
    29. for (const key in Obj) {
    30. resultObj[key] = Obj[key]
    31. }
    32. // 循环复制完毕后返回复制完毕的对象或者数组
    33. return resultObj
    34. }
    35. else {
    36. throw new Error("两个参数必须存在而且要求参数的类型相同,类型同为数组或者对象")
    37. }
    38. }
    39. //判断是否是数组
    40. function isArray(obj) {
    41. return Object.prototype.toString.call(obj) == '[object Array]';
    42. }
    43. //判断是否是对象
    44. function isObject(obj) {
    45. return Object.prototype.toString.call(obj) == '[object Object]';
    46. }
    47. </script>

    四、深拷贝

    封装深拷贝函数

    1. <script>
    2. // -----------------------利用递归和for in 实现对象的深拷贝----------------------
    3. // 1.拷贝的数据源对象
    4. const obj = {
    5. name: "hsq",
    6. age: 18,
    7. color: ["red", 1, false, undefined, null],
    8. children: {
    9. name: 'xxx',
    10. age: 12
    11. },
    12. say: function () {
    13. console.log('enenen');
    14. }
    15. }
    16. //2.调用深拷贝函数将数据源obj进行深拷贝并返回拷贝好的对象,使用testObj常量接收
    17. const testObj = deepObjClone({}, obj)
    18. //3.修改数据源对象中的引用类型属性color数组的第一项
    19. obj.color[0] = "hhh"
    20. //4.打印通过深拷贝成功的对象的引用类型属性color数组的第一项,发现深拷贝的数据发生没有更改
    21. console.log(testObj.color[0]);//red
    22. //深拷贝函数
    23. function deepObjClone(resultObj, Obj) {
    24. //两个参数必须存在而且要求参数的类型相同,类型同为数组或者对象
    25. const verify1 = resultObj && isArray(resultObj) && Obj && isArray(Obj)//参数校验1
    26. const verify2 = resultObj && isObject(resultObj) && Obj && isObject(Obj)//参数校验2
    27. if (verify1 || verify2) {
    28. //使用for in递归循环进行深拷贝
    29. for (const key in Obj) {
    30. //ObjTtem存储遍历数组或者对象的每一项属性值
    31. let ObjTtem = Obj[key]
    32. //遍历的属性值为数组
    33. if (ObjTtem instanceof Array) {
    34. //为拷贝对象添加属性,属性值为数组,数组内容由递归填充
    35. resultObj[key] = deepObjClone([], ObjTtem)
    36. }
    37. //遍历的属性值为函数对象
    38. else if (ObjTtem instanceof Function) {
    39. resultObj[key] = cloneFunction(ObjTtem)
    40. }
    41. //遍历的属性值为普通对象
    42. else if (ObjTtem instanceof Object) {
    43. //为拷贝对象添加属性,属性值为对象,对象内容由递归填充
    44. resultObj[key] = deepObjClone({}, ObjTtem)
    45. }
    46. //遍历的属性值为普通数据类型时直接赋值给拷贝对象的属性
    47. else {
    48. resultObj[key] = ObjTtem
    49. }
    50. }
    51. return resultObj
    52. }
    53. else {
    54. throw new Error("两个参数必须存在而且要求参数的类型相同,类型同为数组或者对象")
    55. }
    56. }
    57. //判断是否是数组
    58. function isArray(obj) {
    59. return Object.prototype.toString.call(obj) === '[object Array]';
    60. }
    61. //判断是否是对象
    62. function isObject(obj) {
    63. return Object.prototype.toString.call(obj) === '[object Object]';
    64. }
    65. //深拷贝函数
    66. function cloneFunction(fn) {
    67. //参数验证
    68. if (!(fn && fn instanceof Function)) {
    69. throw new Error("参数为必须并且参数类型为函数")
    70. }
    71. // 将函数转成字符串
    72. let str = fn.toString()
    73. //截取函数体内容字符串
    74. let subStr = str.substring(str.indexOf("{") + 1, str.lastIndexOf("}"))
    75. // 利用截取函数体内容的字符串和函数的构造器生成新的函数并返回
    76. return new Function(subStr)
    77. }
    78. </script>

  • 相关阅读:
    在虚拟机上在线安装mysql
    【机器学习】决策树算法理论:算法原理、信息熵、信息增益、预剪枝、后剪枝、算法选择
    基于 Netty + RXTX 的无协议 COM 通讯案例实现
    数据结构之七大排序
    【数据集】Maple-IDS——网络安全恶意流量检测数据集
    如果你已经学会了Python编程基础知识,那么下一步?
    go语言结构体使用小结
    高精度随流检测技术助力金融行业实现智能运维
    大模型的无限上下文与数据集组合艺术
    [go学习笔记.第十章.面向对象编程] 10.面向对象的特性-接口
  • 原文地址:https://blog.csdn.net/h18377528386/article/details/126662137