你所不知道的 JavaScript 深浅拷贝

直接赋值 (引用)、浅拷贝、深拷贝

区别

  • 直接赋值 (引用): 其实就是对象的引用(别名)
  • 浅拷贝: 拷贝父对象,不会拷贝对象的内部的子对象
  • 深拷贝: 完全拷贝了父对象及其子对象

解析

  1. b = a: 赋值引用,a 和 b 都指向同一个对象
  1. b = a.copy(): 浅拷贝, a 和 b 是一个独立的对象,但他们的子对象还是指向统一对象(是引用)
  1. b = copy.deepcopy(a): 深度拷贝, a 和 b 完全拷贝了父对象及其子对象,两者是完全独立的

实现

浅拷贝

  1. 对象:Object.assign()
javascript 复制代码
var obj = {a:{a:"kobe",b:39}}
var initalObj = Object.assign({},obj)
initalObj.a.a = "wade"
console.log(obj.a.a) //wade

这个 API 还可用于 对象合并

javascript 复制代码
const ul = {name:"zhangsan"}
const u2 = {age: 12}
const u3 = Object.assign(ul,u2);
console.log(u3) // { name:'zhangsan',age: 12 }

object 只有一层的时候,是 深拷贝

  1. 数组:concat、slice
javascript 复制代码
let arr1 = [ 1, 3, {
    username:'kobe'
}]

let arr2 = arr1.slice() // 或者 let arr2 = arr.concat()

arr2[1] = 2
arr2[2].username = '6666'
console.log(arr1, arr2)

Arraysliceconcat 方法不修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组

深拷贝

  1. 扩展运算符,也可以进行 浅拷贝
  • 序列化 JSON.parse(JSON.stringify())
  • 缺点:虽然可以实现数组或对象深拷贝,但不能处理函数
  1. 递归遍历 手写实现
javascript 复制代码
// 定义检测数据类型的功能函数
function checkedType(target){
    return Object.prototype.toString.call(target).slice(8,-1)
}

// 实现深度克隆---对象/数组
function clone(target){
    // 判断拷贝的数据类型
    // 初始化变量result 成为最终克隆的数据
    let result,targetType = checkedType(target)
    if(targetType === 'Object'){
        result = {}
    }else if(targetType === 'Array'){
        result = []
    }else{
        return target
    }
    // 遍历目标数据
    for(let i in target){
        // 获取遍历数据结构的每一项值
        let value=target[i]
        // 判断目标结构里的每一值是否存在对象/数组
        if(checkedType(value) === 'Object' || checkedType(value) === 'Array'){ //对象/数组里嵌套了对象/数组
            // 继续遍历获取到value值
            result[i] = clone(value)
        }else{ //获取到value值是基本的数据类型或者是函数
            result[i] = value;
        }
    }
    return result
}

原理:递归遍历所有对象、数组,直到都是基本数据类型,然后再去复制,就是深拷贝

  1. 第三方函数库 loadsh
相关推荐
范文杰3 分钟前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪11 分钟前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪20 分钟前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy1 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom2 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom2 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom2 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom2 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom2 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试
LaoZhangAI3 小时前
2025最全GPT-4o图像生成API指南:官方接口配置+15个实用提示词【保姆级教程】
前端