前端基础知识库-JavaScript对象的深拷贝

简介: 在JavaScript数据类型分为基础类型和引用类型,而引用类型又称为对象,可见了解对象是我们真正掌握JavaScript语言的必备技能。本章主要与大家一起去探索JavaScript对象的一些经常被我们忽略的以及难以理解的知识。好了,废话不多说让我们一起进入JavaScript对象的世界吧。

前言


-路漫漫其修远兮,我将上下而求索。

在JavaScript数据类型分为基础类型和引用类型,而引用类型又称为对象,可见了解对象是我们真正掌握JavaScript语言的必备技能。本章主要与大家一起去探索JavaScript对象的一些经常被我们忽略的以及难以理解的知识。好了,废话不多说让我们一起进入JavaScript对象的世界吧。

基本概念


  • 个人理解:深浅拷贝在JavaScript中只是对于引用类型来说的,因为在JavaScript中基本数据类型是通过值传递的,所以他们不存在深拷贝一说。
  • 对象的浅拷贝:即只复制对象在栈内存中的保存的地址值,例如我们直接用赋值符号拷贝另一个对象的值。
  • 对象的深拷贝:复制对象存在堆内存中的实际值并且重新在栈内存中生成一份指向新堆内存中的地址值。
  • 原因:JavaScript中的引用类型的数据是被存放在堆内存中的,他们在栈内存中的变量只是保存了一个指向对堆内存中值的指针(类似与c中的指针),因此我们在访问引用类型的数据时只能先从栈中取出对象的指针地址,然后才会从堆内存中取得对象的数据。这也是JavaScript对象用赋值符号只能复制指针地址的原因。

为何进行对象深拷贝


  • 如果只是对对象数据类型进行简单的浅拷贝,则新复制的值和老值会共用堆内存中的数据,导致值不确定性,例如:
let a={
    val:"test"
}
console.log(a.val)//"test"
let b=a
b.val="test2"
console.log(a.val)//"test2"
console.log(b.val)//"test2"

这也是导致前端显示异常的根本原因之一

  • 提高代码可维护性,多人合作开发时,共用某份是对象类型的数据如果只进行简单的浅拷贝则很影响他人。

深拷贝的方法

  • JSON.stringfy() => JSON.parse() 即将一个对象先解析为json 字符串然后再解析
let a={
    val:'test'
}
let b=JSON.parse(JSON.stringfy(a))

优点:操作简单。

缺点:1.如果对象很大会占用内存 2.对于复杂的对象类型(即属性是诸如 Map, Set, RegExp, Date, ArrayBuffer,function和其他内置类型),在进行序列化时会丢失。 丢失属性。3.无法进行对象的循环处理。

  • 使用object.assign()来实现:
let originobj= {
  'name': 'test',
  'weight': 50
};
let newobj = Object.assign({}, originobj, {
  'test': '111'
});
newobj.age = 60;
console.log('originobj', originobj); //{name: "test", weight: 50}
console.log('newobj', newobj); //{name: "test", weight: 50, test: "111", age: 60}

优点:方便快捷 不会丢失原数据 缺点:只能复制简单的对象(),即Object.assign()拷贝的只是属性值 注意:如果对象中的属性还是对象则Object.assign()不会进行值拷贝,只能进行引用拷贝

  • 为了解决JSON和assign复制带来的问题,我们可以采用循环递归复制,即在遍历赋值对象属性的时候,遇到属性是引用类型的,则把这个属性展开赋值,如下代码所示:
function cloneDeep(newobj={},originObj){
    for(let key in originObj){
        //判断是否是对象类型
        if(originObj[key] && originObj[key] instanceof object){
            //递归将对象类型赋值给新数组
            newobj[key] = cloneDeep(originObj[key])
        }else{
            newobj[key] = originObj[key]
        }
    }
    return newobj
}
let obj = {a:{b:'test'},c:"test2"}
//此时完全copy了obj的值
let obj1 = cloneDeep(obj)//{a:{b:'test'},c:"test2"}

总结


在编程的世界中熟悉某一门语言的基本要求就是掌握这门语言定义的数据类型,不同的语言中所定义的数据类型往往不同。这也是我们同时掌握多中编程语言的难点。但幸运的是他们底层设计原理都是相互借鉴的,这也成为了我们能够掌握夺门语言的关键点之一。


相关文章
|
9天前
|
存储 JavaScript 前端开发
|
1天前
|
前端开发 JavaScript
Vue前端渲染blob二进制对象图片的方法
Vue前端渲染blob二进制对象图片的方法
9 0
|
7天前
|
前端开发 JavaScript Linux
若依修改之后,无法访问前端项目如何解决,只能访问后端的接口,我的接口8083,端不显示咋解决?在vue.config.js文件中的映射路径要跟后端匹配,到软件商店里找到Ngnix配置代理,设80不用加
若依修改之后,无法访问前端项目如何解决,只能访问后端的接口,我的接口8083,端不显示咋解决?在vue.config.js文件中的映射路径要跟后端匹配,到软件商店里找到Ngnix配置代理,设80不用加
|
8天前
|
JavaScript
js 简易对象转字符串后恢复为简易对象(如 ^a=$1^b=2转对象)
js 简易对象转字符串后恢复为简易对象(如 ^a=$1^b=2转对象)
8 0
|
9天前
|
JavaScript
js 数组移除指定元素【函数封装】(含对象数组移除指定元素)
js 数组移除指定元素【函数封装】(含对象数组移除指定元素)
8 0
|
9天前
|
JavaScript
JS 数组去重(含简单数组去重【5种方法】、对象数组去重【2种方法】)
JS 数组去重(含简单数组去重【5种方法】、对象数组去重【2种方法】)
13 0
|
9天前
|
JavaScript 前端开发 测试技术
js 控制台调试——console 对象【详解】
js 控制台调试——console 对象【详解】
14 0
|
9天前
|
JavaScript
js 内建对象的拓展 shim/polyfill ( 内含js 判断对象的属性是否存在的方法)
js 内建对象的拓展 shim/polyfill ( 内含js 判断对象的属性是否存在的方法)
10 0
|
9天前
|
前端开发 JavaScript
前端深拷贝、浅拷贝,一起手撕深拷贝
【7月更文挑战第2天】JavaScript中的深拷贝和浅拷贝关乎对象复制的独立性。浅拷贝(如`Object.assign()`、扩展运算符)创建新对象,但共享引用类型属性的内存地址,导致修改新对象会影响原始对象。深拷贝(如递归复制)创建完全独立的对象副本,不受原始对象变动影响。`JSON.parse(JSON.stringify(obj))`是简单的深拷贝方法,但无法处理函数、undefined、Symbol及循环引用。手动实现深拷贝需递归遍历并处理循环引用问题,以确保复制的完整性。理解这两者差异对编写健壮的代码至关重要。
7 0
|
10天前
|
前端开发 JavaScript API
只会用插件可不行,这些前端动画技术同样值得收藏-JavaScript篇(下)
只会用插件可不行,这些前端动画技术同样值得收藏-JavaScript篇(下)
11 0