你不容错过的JavaScript高级语法(深拷贝)

简介: 你不容错过的JavaScript高级语法(深拷贝)

下面一篇文章我们来实现一下深拷贝。


深拷贝的介绍


通过定义的方法,拷贝出的对象和原来的对象没有关系。修改任何对象都不会相互影响。


通过JSON方法来处理深拷贝


const info = JSON.parse(JSON.stringify(obj))


存在的问题:


  • 对于函数、Symbol等是无法处理的


  • 存在对象的循环引用,也会报错的


自定义深拷贝函数


  • 基本封装


  • 他只能处理基本数据类型, 对象, 数组。


  • 不能处理Symbol, Function, Set, Map类型


function isObject(value) {
      const valueType = typeof value
      return (value !== null) && (valueType === "object" || valueType === "function")
    }
    function deepClone(originValue) {
      // 判断传入的originValue是否是一个对象类型
      if (!isObject(originValue)) {
        return originValue
      }
      // 判断传入的对象是数组, 还是对象
      const newObject = Array.isArray(originValue) ? []: {}
      for (const key in originValue) { // 如果originValue是一个函数(其实任何值都不会报错)in操作符也不会报错。
        newObject[key] = deepClone(originValue[key])
      }
      return newObject
    }


  • 处理函数类型。


// 判断如果是函数类型, 那么直接使用同一个函数
      if (typeof originValue === "function") {
        return originValue
      }


  • 处理Symbol类型


  • Symbol作为值是可以直接拷贝的。


  • 由于for ... of不能遍历Symbol为key的对象,所以需要做特殊处理。


// 判断如果是Symbol的value, 那么创建一个新的Symbol
      if (typeof originValue === "symbol") {
        return Symbol(originValue.description)
      }
      // 对Symbol的key进行特殊的处理
      const symbolKeys = Object.getOwnPropertySymbols(originValue)
      for (const sKey of symbolKeys) {
        newObject[sKey] = deepClone(originValue[sKey])
      }


  • 处理Set, Map类型


  • 注意: 这里只对Set,Map类型做浅拷贝。


// 判断是否是一个Set类型
      if (originValue instanceof Set) {
        return new Set([...originValue])
      }
      // 判断是否是一个Map类型
      if (originValue instanceof Map) {
        return new Map([...originValue])
      }


  • 处理对象循环引用问题


  • 通过Map来实现,就是先把对象放进Map中。每次遍历,如果遇到循环引用,那么直接将newObject赋值给他。


  • 并且为了防止多次调用,自由变量Map中的值过多,应该将Map作为参数传递。


function isObject(value) {
      const valueType = typeof value
      return (value !== null) && (valueType === "object" || valueType === "function")
    }
    function deepClone(originValue, map = new WeakMap()) {
      // 判断是否是一个Set类型
      if (originValue instanceof Set) {
        return new Set([...originValue])
      }
      // 判断是否是一个Map类型
      if (originValue instanceof Map) {
        return new Map([...originValue])
      }
      // 判断如果是Symbol的value, 那么创建一个新的Symbol
      if (typeof originValue === "symbol") {
        return Symbol(originValue.description)
      }
      // 判断如果是函数类型, 那么直接使用同一个函数
      if (typeof originValue === "function") {
        return originValue
      }
      // 判断传入的originValue是否是一个对象类型
      if (!isObject(originValue)) {
        return originValue
      }
      if (map.has(originValue)) {
        return map.get(originValue)
      }
      // 判断传入的对象是数组, 还是对象
      const newObject = Array.isArray(originValue) ? []: {}
      map.set(originValue, newObject)
      for (const key in originValue) {
        newObject[key] = deepClone(originValue[key], map)
      }
      // 对Symbol的key进行特殊的处理
      const symbolKeys = Object.getOwnPropertySymbols(originValue)
      for (const sKey of symbolKeys) {
        // const newSKey = Symbol(sKey.description)
        newObject[sKey] = deepClone(originValue[sKey], map)
      }
      return newObject
    }



相关文章
|
30天前
|
JavaScript 前端开发
JavaScript中的深拷贝与浅拷贝
JavaScript中的深拷贝与浅拷贝
31 2
|
30天前
|
JavaScript 前端开发
js中浅拷贝,深拷贝的实现
js中浅拷贝,深拷贝的实现
24 0
|
30天前
|
存储 JavaScript 前端开发
Node.js的基本语法
【8月更文挑战第12天】Node.js的基本语法
75 1
|
28天前
|
JavaScript 前端开发
JavaScript基础&实战(1)js的基本语法、标识符、数据类型
这篇文章是JavaScript基础与实战教程的第一部分,涵盖了JavaScript的基本语法、标识符、数据类型以及如何进行强制类型转换,通过代码示例介绍了JS的输出语句、编写位置和数据类型转换方法。
JavaScript基础&实战(1)js的基本语法、标识符、数据类型
|
1月前
|
JavaScript 前端开发
JavaScript中的深拷贝和浅拷贝的实现讲解
在JavaScript中,浅拷贝与深拷贝用于复制对象。浅拷贝仅复制基本类型属性,对于引用类型仅复制引用,导致双方共享同一数据,一方修改会影响另一方。深拷贝则完全复制所有层级的数据,包括引用类型,确保双方独立。浅拷贝可通过简单属性赋值实现,而深拷贝需递归复制各层属性以避免共享数据。
35 1
|
27天前
|
前端开发 JavaScript 程序员
前端 JavaScript 的 _ 语法是个什么鬼?
前端 JavaScript 的 _ 语法是个什么鬼?
|
27天前
|
JavaScript 前端开发
js中浅拷贝和深拷贝的区别
js中浅拷贝和深拷贝的区别
22 0
|
2月前
|
缓存 JavaScript 前端开发
前端框架与库 - Vue.js基础:模板语法、数据绑定
【7月更文挑战第14天】Vue.js 是渐进式框架,以简洁API和高效数据绑定知名。本文聚焦模板语法与数据绑定,解释常见问题和易错点,助力初学者避坑。模板语法中,{{ expression }} 用于渲染值,v-bind/: 用于动态绑定属性。数据绑定涉及文本、属性和事件,注意v-model适用于表单元素,计算属性有缓存。理解正确用法,借助文档和IDE,可提升开发质量和效率。善用Vue.js,打造响应式UI。
61 4
|
2月前
|
存储 JavaScript 前端开发
|
2月前
|
前端开发 JavaScript
js【详解】Promise(含 Promise 的三种状态及其变化,创建 Promise, Promise.all 语法、Promise.all 实战范例、手写 Promise.all)
js【详解】Promise(含 Promise 的三种状态及其变化,创建 Promise, Promise.all 语法、Promise.all 实战范例、手写 Promise.all)
134 0