START

  • 番茄我又又又来写点啥啦。
  • 最近敲代码,总是遇到需要修改数据,在前端展示。但是最后并不想修改原数据的情况。所以,需要涉及到数据的拷贝了,数据拷贝又分深拷贝,浅拷贝。所以写一篇文章记录一下。
  • 本文仅个人的想法,能力有限,参考即可,后续对这个有更深入的理解了,再补充。
  • 啰嗦一句,深拷贝浅拷贝 和 深克隆浅克隆,其实都差不多一个意思啦,看个人习惯如何称呼。

JS 的数据类型

在说深浅克隆之前,我想提一下JS的数据类型。

  • JS数据类型,可以大致分为两种:基本数据类型引用数据类型

  • 基本数据类型:

  1. Undefined
  2. Null
  3. Boolean
  4. Number
  5. String
  • 引用数据类型:
  1. object
  • 当然 ES6 引入了一种新的数据类型 Symbol (这里暂时不讨论 Symbol)

为什么要这样区分数据类型呢?

  • 因为基本数据类型数据,保存在栈内存
  • 引用类型保存在堆内存中

那么为什么要分两种保存方式呢?

  • 根本原因是在于保存在栈内存的必须是大小固定的数据,引用的类型的大小不固定,只能保存在堆内存中。但是我们可以将引用类型的地址存储在栈内存中。

  • 文字不好理解的话,举个例子:

    // 1.定义一个基本数据类型--数字类型的变量
    var a = 1// 定义一个引用类型的变量
    var obj = {name: "lazy_tomato"
    }
    
  • 上面代码执行后,在内存中其实就是这样的。

知道js变量的保存方式有什么用呢?

  • 看一看简单的题目就知道了。

题目一

var a = 1var b = aconsole.log('变量a为:', a, "变量b为:", b);  //变量a为: 1 变量b为: 1a = 88console.log('变量a为:', a, "变量b为:", b);   //变量a为: 88 变量b为: 1

题目二

var a = {name: '张三',age: 14
}var b = aconsole.log('变量a为:', a, "变量b为:", b);
//变量a为: { name: '张三', age: 14 } 变量b为: { name: '张三', age: 14 }a.name = 'lazy_tomato'console.log('变量a为:', a, "变量b为:", b);
//变量a为: { name: 'lazy_tomato', age: 14 } 变量b为: { name: 'lazy_tomato', age: 14 }
  • 题目一中,为什么我修改a,不会修改b ?

  • 题目二中,为什么我修改a,会同时修改b ?

    正是因为题目二中,我们 var b = a 做的操作就是:

    声明一个变量b,b栈内存中存储的地址,和a一样,都指向

    {
    name: ‘张三’,
    age: 14
    }

    所以 a.name = 'lazy_tomato' 执行后 a指向堆内存中为:

    {
    name: ‘lazy_tomato’,
    age: 14
    }

    但是 b栈内存中存储的地址也指向这个对象,所以 修改a,会同时修改b

浅拷贝

  • 浅拷贝: 创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。

  • 看不懂定义?那就简单点说: 就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。

  • 题目二,其实就是属于浅拷贝,修改了变量a,变量b也跟着改变。

浅拷贝实现方式

  1. 可以通过简单的赋值实现

    类似上面的例子

  2. 利用 Object.assign()实现

Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign() 进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。

var obj = { a: { a: "hello", b: 21 } };var newObj = Object.assign({}, obj);console.log("obj变量为:", obj, "newObj: ", newObj)
//obj变量为: { a: { a: 'hello', b: 21 } } newObj:  { a: { a: 'hello', b: 21 } }newObj.a.a = "lazy_tomato";console.log("obj变量为:", obj, "newObj: ", newObj)
//obj变量为: { a: { a: 'lazy_tomato', b: 21 } } newObj:  { a: { a: 'lazy_tomato', b: 21 } }

注意:当object只有一层的时候,是深拷贝,例如如下:

var obj1 = { a: 10, b: 20, c: 30 };
var obj2 = Object.assign({}, obj1);console.log(obj1, obj2);
//{ a: 10, b: 20, c: 30 } { a: 10, b: 20, c: 30 }obj1.b = 100;
console.log(obj1, obj2);
//{ a: 10, b: 100, c: 30 } { a: 10, b: 20, c: 30 }

深拷贝

  • 深拷贝: 将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象

深拷贝实现方式

1、对象只有一层的话可以使用上面的:Object.assign()函数
2、转成 JSON 再转回来
var obj1 = { body: { a: 10 } };
var obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj1, obj2)  //{ body: { a: 10 } } { body: { a: 10 } }
obj1.body.a = 20;
console.log(obj1, obj2) //{ body: { a: 20 } } { body: { a: 10 } }

缺点

  • 拷贝对象的值,如果存在函数、undefined、symbol,在经过JSON.stringify()序列化后的JSON字符串中这个键值对会消失;
  • 没办法拷贝不可枚举的属性,也不像for in 那样可以拷贝原型上的数据;
  • 拷贝Date引用类型会变成字符串
  • 拷贝RegExp 、Error 引用类型会变成 空对象
  • 对象中含有NaN,Infinity和-Infinity,则序列化的结果会变成null
3、递归拷贝
  • 写个函数实现递归拷贝
function deepClone(initalObj, finalObj) {    var obj = finalObj || {};    for (var i in initalObj) {        var prop = initalObj[i];        if(prop === obj) {            continue;}        if (typeof prop === 'object') {obj[i] = (prop.constructor === Array) ? [] : {};            arguments.callee(prop, obj[i]);} else {obj[i] = prop;}}    return obj;}

参考的相关网站博客

  • 写的很好的个人博客

  • 掘金的文章

END

  • 写着写着,发现自己还有好多不懂的呀,o(╥﹏╥)o,挂出的相关博客都很棒,推荐看看。加油啦~~ 后续对js更加精通了,再来补充这篇文章。
  • 个人记录,参考即可。

前端克隆数据 --JS 深浅拷贝相关推荐

  1. 【学姐面试宝典】前端基础篇Ⅴ——JS深浅拷贝、箭头函数、事件监听等

    前言 博主主页

  2. 9012年,当我们讨论js深浅拷贝时我们在说些什么?

    前言: 本文主要阅读对象:对深浅拷贝印象模糊对初级前端,想对js深浅拷贝聊一聊的中级前端.如果是对这些有完整对认知体系和解决方法的大佬,可以选择略过. 复制代码 正文: 讨论深浅拷贝,首先要从js的基 ...

  3. Mat数据的深浅拷贝

    1.Mat数据的深浅拷贝 拷贝Mat时默认为浅拷贝,只拷贝Header中的内容,数据不变 Mat浅拷贝 Mat A A = imread(file, IMREAD_COLOR) Mat B(A); B ...

  4. 集合 小数据池 深浅拷贝

    set  集合     列表.元组.字符串去重 集合中的元素必须是可哈希(hash)的,但set本身是不可哈希的可变的(有增删改查).不重复.无序的   创建一个空集合 s = set{} 1.关系型 ...

  5. 实现JS深浅拷贝的五种方式

    一.堆栈.基本数据类型.引用数据类型 在了解深浅拷贝之前,我们需得对堆栈.基本数据类型.引用数据类型有基本的了解 基本数据类型:number.string.boolean.null.undefined ...

  6. JS中深浅拷贝 函数封装代码

    一.了解 基本数据类型保存在栈内存中,按值访问,引用数据类型保存在堆内存中,按址访问. 二.浅拷贝 浅拷贝只是复制了指向某个对象的指针,而不是复制对象本身,新旧对象其实是同一内存地址的数据,修改其中一 ...

  7. php深浅拷贝,JavaScript 中的深浅拷贝

    工作中经常会遇到需要复制 JavaScript 数据的时候,遇到 bug 时实在令人头疼:面试中也经常会被问到如何实现一个数据的深浅拷贝,但是你对其中的原理清晰吗?一起来看一下吧! 一.为什么会有深浅 ...

  8. Python的深浅拷贝讲解!

    ↑↑↑关注后"星标"Datawhale 每日干货 & 每月组队学习,不错过 Datawhale干货 作者:皮钱超,厦门大学,Datawhale原创作者 本文约3000字,建 ...

  9. 【Python基础】Python的深浅拷贝讲解

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 前言 在很多语言中都存在深浅拷贝两种拷贝数据的方式,Python中 ...

  10. js之深浅克隆(深浅拷贝)

    目录 1.浅克隆(浅拷贝) 2.深克隆(深拷贝) 总结 1.浅克隆(浅拷贝) 无法进行引用类型(地址和地址中数据的)双重拷贝,从而导致克隆者和被克隆者指向同一地址后,任何一方发生数据的改变都会影响对方 ...

最新文章

  1. qml学习笔记(二):可视化元素基类Item详解(上半场anchors等等)
  2. java jmx连接不上_JMX连接服务端失败
  3. 【转】HTML5 本地存储五种方案
  4. 数据库设计之从0到1 教你如何设计E-R图
  5. C++ 引用本质就是一个指针常量
  6. 苹果禁用FaceTime多人聊天功能:漏洞将很快修复
  7. mysql连接查询_.net core 里连接mysql查询数据的方法
  8. 手机端页面自适应解决方案—rem布局进阶版
  9. python local global_Python 变量作用域 LEGB (上)—— Local,Global,Builtin
  10. 考不上本科是智商问题,这话有错吗?
  11. proteus中ISIS软件的各种器件的添加
  12. C语言——指针详解(必收藏)
  13. Web前端笔记和简历模板
  14. Java 中的 IO 和 NIO
  15. kotlin android 开源,Kotlin开源项目集合
  16. 数据治理之数据质量管控流程(参考)
  17. ACER-4738ZG 拆机改散热
  18. Elasticsearch中object类型与nested类型之间的区别
  19. Java中的动态代理详解
  20. PLC通讯实现-C#实现西门子PLC以太网通讯Sharp7(六)

热门文章

  1. 基于Maven的SSM总体架构设计(四)
  2. django.db.utils.DataError: (1366, “Incorrect string value: ‘\\xE5\\x85\\xAD\\xE5\\x8D\\x83‘ for colu
  3. linux 系统找回密码,Linux系统密码忘记后的五种恢复方法
  4. 各行各业求职-招聘QQ群欢迎加入
  5. 南京商标注册流程是什么
  6. discuz template 模板文件说明
  7. 最受IT公司欢迎的30款开源软件
  8. 计算机连上wifi无法上网了,电脑已连接wifi但无法上网 已连接wifi但电脑无法上网-192路由网...
  9. 基于python+django框架+Mysql数据库的校园运动场地预约系设计与实现
  10. 4n35光耦引脚图_常见的高速光耦引脚图