你所不知道的 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
相关推荐
namekong85 小时前
清理谷歌浏览器垃圾文件 Chrome “User Data”
前端·chrome
开发者小天6 小时前
调整为 dart-sass 支持的语法,将深度选择器/deep/调整为::v-deep
开发语言·前端·javascript·vue.js·uni-app·sass·1024程序员节
李少兄8 小时前
HTML 表单控件
前端·microsoft·html
学习笔记10110 小时前
第十五章认识Ajax(六)
前端·javascript·ajax
消失的旧时光-194310 小时前
Flutter 异步编程:Future 与 Stream 深度解析
android·前端·flutter
曹牧10 小时前
C# 中的 DateTime.Now.ToString() 方法支持多种预定义的格式字符
前端·c#
勿在浮沙筑高台10 小时前
海龟交易系统R
前端·人工智能·r语言
歪歪10010 小时前
C#如何在数据可视化工具中进行数据筛选?
开发语言·前端·信息可视化·前端框架·c#·visual studio
Captaincc11 小时前
AI 能帮你写代码,但把代码变成软件,还是得靠人
前端·后端·程序员
吃饺子不吃馅12 小时前
如何设计一个 Canvas 事件系统?
前端·canvas·图形学