首页 > 编程语言 >JavaScript的深拷贝和浅拷贝

JavaScript的深拷贝和浅拷贝

时间:2022-10-18 00:56:38浏览次数:57  
标签:bestFriend name age JavaScript newObj stu 拷贝

一、前言

  首先, 我们了解 JavaScript 中的数据类型主要分为:

  基本数据类型:
    NumberStringBooleannullundefinedSymbolBigint

  引用数据类型:
    Object

  其中,引用数据类型的值是保存在栈内存和堆内存中的对象,栈区保存变量的标识符和指向堆内存该对象的指针。当使用引用值时,解析器会先往栈区寻找地址,然后根据地址找到堆内存中的实体。

二、浅拷贝

  先说浅拷贝,浅拷贝就是只拷贝对象的表层,如果内部数据有对象或数组,那么只会拷贝到该属性在栈中的地址。

  新旧数据此时引用的是同一片数据,只要一个改变就都会改变。

let stu = {
    name: '小红',
    age: 108,
    bestFriend: {
        name: '小军',
        age: 26,
    },
}

// 通过函数拷贝
function copyObject(obj) {
    let newObj = {}

    for (let i in obj) {
        newObj[i] = obj[i]
    }

    return newObj
}
let newObj_1 = copyObject(stu)

// 通过拓展运算符拷贝
let newObj_2 = {
    ...stu
}

// 先输出查看数据
console.log(stu) //      { name: '小红', age: 108, bestFriend: { name: '小军', age: 26 } }
console.log(newObj_1) // { name: '小红', age: 108, bestFriend: { name: '小军', age: 26 } }
console.log(newObj_2) // { name: '小红', age: 108, bestFriend: { name: '小军', age: 26 } }

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

// 修改源数据的表层数据:源数据改变不影响拷贝出来的数据
stu.name = '张三'
console.log(stu) //      { name: '张三', age: 108, bestFriend: { name: '小军', age: 26 } }
console.log(newObj_1) // { name: '小红', age: 108, bestFriend: { name: '小军', age: 26 } }
console.log(newObj_2) // { name: '小红', age: 108, bestFriend: { name: '小军', age: 26 } }

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

// 修改源数据的里层数据: 一个改变其余跟着改变
stu.bestFriend.name = '李四'
console.log(stu) //      { name: '张三', age: 108, bestFriend: { name: '李四', age: 26 } }
console.log(newObj_1) // { name: '小红', age: 108, bestFriend: { name: '李四', age: 26 } }
console.log(newObj_2) // { name: '小红', age: 108, bestFriend: { name: '李四', age: 26 } }

三、深拷贝

  深拷贝不像浅拷贝那样只拷贝一层,而是层层拷贝。

  新旧数据是完全分离的, 互不影响, 修改一个不会影响另一个

3.1 通过递归实现深拷贝

只是实现一个简单的深拷贝, 不是最佳

let stu = {
    name: '小红',
    age: 108,
    bestFriend: {
        name: '小军',
        age: 26,
    },
    arr: [0, 1]
}

function copyObject(obj) {
    let newObj = null

    if (obj instanceof Array) {
        newObj = []
    } else {
        newObj = {}
    }

    // 拷贝的算法
    for (let i in obj) {
        // newObj[i] = obj[i]
        // 在浅拷贝代码的基础上,在这里添加判断
        //     如果某一项是一个引用类型,就递归调用拷贝的这个函数
        if (obj[i] instanceof Object) {
            newObj[i] = copyObject(obj[i])
        } else {
            newObj[i] = obj[i]
        }
    }

    return newObj
}

let newObj = copyObject(stu)

// 修改源数据的浅层数据、深层对象中的数据、深层数组中的数据
stu.name = '小刚'
stu.bestFriend.name = '李四'
stu.arr.push(3)

console.log(stu)
console.log(newObj)
// { name: '小刚', age: 108, bestFriend: { name: '李四', age: 26 }, arr: [ 0, 1, 3 ] }
// { name: '小红', age: 108, bestFriend: { name: '小军', age: 26 }, arr: [ 0, 1 ] }

3.2 通过 JSON.parse 实现深拷贝

注意:

JSON.parse() 虽然简单,但是有一些缺陷:

  1. 对象的属性值是函数时,无法拷贝
  2. 原型链上的属性无法拷贝
  3. 不能正确的处理 Date 类型的数据
  4. 不能处理 RegExp
  5. 会忽略 Symbol
  6. 会忽略 undefined
let stu = {
    name: '小红',
    age: 108,
    bestFriend: {
        name: '小军',
        age: 26,
    },
    arr: [0, 1],
}

function copyObject(obj) {
    let newStr = JSON.stringify(obj)
    let newObj = JSON.parse(newStr)
    return newObj

    // 上面三行可以简化为:
    // return JSON.parse(JSON.stringify(obj))
}

let newObj = copyObject(stu)

// 修改源数据的浅层数据、深层对象中的数据、深层数组中的数据
stu.name = '小刚'
stu.bestFriend.name = '李四'
stu.arr.push(3)

// 查看新旧数据是否发生变化
console.log(stu)
console.log(newObj)
// { name: '小刚', age: 108, bestFriend: { name: '李四', age: 26 }, arr: [ 0, 1, 3 ] }
// { name: '小红', age: 108, bestFriend: { name: '小军', age: 26 }, arr: [ 0, 1 ] }

标签:bestFriend,name,age,JavaScript,newObj,stu,拷贝
From: https://www.cnblogs.com/bkzj/p/16801229.html

相关文章

  • javascript对象数组内元素排序
    数组内对象排序数组项是对象,需要根据数组项的某个属性对数组进行排序。注意:想往后排的,后面的-前面的  a.age-b.age,如果是从小到大排序,大的-小的letperson=[......
  • JavaScript输入输出语句propmt、alert、console
    propmt是一个输入语句它的返回结果是你输入的内容,无论输入什么内容返回结果的数据类型都是字符串类型。alert是一个弹框输出console是控制台输出 下面代码的意思是输......
  • Python与JavaScript交互
    介绍“胶水”语言Python很擅长于其他语言交互,本文介绍如何与JavaScript来交互。 ......
  • 【Java】Java中的零拷贝
    物理内存计算机物理内存条的容量,比如我们买电脑会关注内存大小有多少G,这个容量就是计算机的物理内存。虚拟内存操作系统为每个进程分配了独立的虚拟地址空间,也就是虚拟......
  • 12_拷贝
    拷贝1.不可变类型和可变类型知识点:不可变类型:字符串,元组可变类型:列表,字典(它的value值),集合(除了可变类型都是不可变类型)2.浅拷贝和深拷贝知识点:......
  • Design Patterns in JavaScript: Module, Revealing Module
    <html><head></head><body><h1>DesignPatternsinJavaScript:Module,RevealingModule</h1><divid="root"></d......
  • 网页源码加密JavaScript程序,有效压缩和加密JS、Html、Css页面数据
    我们知道,基于Des或Aes对称加密时,当明文和密码相同,则密文相同。而我们此次发布是WJLSymmetricEncryption4.js(点击链接跳转到下载页面)加密程序,当明文和密码相同,每次加密后的......
  • 原生JavaScript
    原生JavaScript为了方便查看.所有的js和css代码都是嵌入式直接写在html代码中1.js的引入方式<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8">......
  • JavaScript笔记
    JavaScript原型链每创建一个函数,解析器都会想函数中添加一个prototype原型属性,这个prototype属性对应着一个对象,这个对象就是原型对象如果该函数是普通函数调用,则proto......
  • javascript: Webcam
     varstop=function(){varstream=video.srcObject;vartracks=stream.getTracks();for(vari=0;i<tracks.length;i++){vartrack=tra......