JavaScript 的 深拷贝和浅拷贝
深拷贝和浅拷贝都是针对的引用类型,
JS中的变量类型分为值类型(基本类型)和引用类型;
对值类型进行复制操作会对值进行一份拷贝,而对引用类型赋值,则会对地址进行拷贝,最终两个变量指向同一份数据
一、先来看看JS中的数据类型
let x = 1; //number类型
let x = 0.1; //number类型,JS不区分整数值和浮点数值 let x = "hello world"; //由双引号内文本构成字符串
let x = 'javascript'; //单引号内文本同样可以构成字符串 let x = true; // boolean 布尔类型 let x = null;
let x = undefined; //null和undefined很相似,是特殊的类型
JS 中数据分为两种类型:
- 原始数据类型
- number
- string
- boolean
- null
- undefined
- 对象数据类型
- array 数组 特殊对象类型
- function 函数 特殊对象类型
- object 对象
还有 undefined 和 null,此处暂不讨论
object对象需要注意的点:
- 对象是可变的,即值是可以修改的
- 对象的比较并非值得比较
比如:var a = [], b = [];
a == b; //false,只有在引用相同(指向的地址相同)时,两个只才会相等
由此可以延伸出 深拷贝和浅拷贝 的问题。
=========================================================================
我们的困惑:
1. 看着相等,却又不等
2. 想要不等,却又相等
那么造成这样问题的原因在哪呢?
> 对象的引用
> 引用只会对地址进行赋值, 所以
1. 不同的变量 a 和 b,他们的地址不同,即使数据相同,本身也不会相等,这是造成困惑一的原因;
2. 而变量 aa 和 bb 指向同一地址,当该地址的数据改变时,所有使用该地址的变量全部改变(同一数据),这是造成困惑二的原因
达不到我们想要的效果,怎么办呢?
二、引用(对象)数据类型的赋值和比较问题
解决办法: 笨办法,也是唯一的方式,既然对象数据类型 是由基本数据类型组成的,而基本数据类型可以正常赋值、比较,那我们就把对象类型变成一个个的基本类型进行操作
方法一: 遍历对象中的内容,一个一个的进行赋值,这样只进行一层拷贝的方式了,就是浅拷贝
// 浅拷贝方法
function shallowClone(source) {
let target = {};
for(leti in source) {
if (source.hasOwnProperty(i)) {
target[i] = source[i];
}
}
return target;
}
方法二: 相对于一层拷贝的浅拷贝,无线层次的拷贝叫做 深拷贝
// 简单深拷贝
function clone(source) {
let target = {};
for(let i in source) {
if (source.hasOwnProperty(i)) {
if (typeof source[i] === 'object') {
target[i] = clone(source[i]); // 判断仍是对象,就进行递归
} else {
target[i] = source[i];
}
}
}
return target;
}
上面 clone 方法 和 shallowClone 方法的 区别就是 多了 递归
但是仍然有些问题需要注意:
- 参数需要检验
- 判断是否对象的逻辑不够严谨
- 需要考虑数组的情况
暂不细说,判断对象可以用此方法:
// 更严谨的判断对象的方法
function isObject(x) {
return Object.prototype.toString.call(x) === '[object Object]';
}
当然我们也可以参考其他方法或使用插件
比如: 简单粗暴的 JSON.parse(JSON.stringify(oldObj))
比如: ES6的assign方法(浅拷贝)
比如: 通过immutableJS实现深拷贝
三、最后
无论 浅拷贝,还是深拷贝 都会带来性能问题(平白的需要遍历,只是重新赋值)
所以我们对象最好写的浅一点,精简一点。。。
详细可以看这篇: https://yanhaijing.com/javascript/2018/10/10/clone-deep/
JavaScript 的 深拷贝和浅拷贝的更多相关文章
- javascript对象深拷贝,浅拷贝 ,支持数组
javascript对象深拷贝,浅拷贝 ,支持数组 经常看到讨论c#深拷贝,浅拷贝的博客,最近js写的比较多, 所以也来玩玩js的对象拷贝. 下面是维基百科对深浅拷贝的解释: 浅拷贝 One meth ...
- 也来玩玩 javascript对象深拷贝,浅拷贝
经常看到讨论c#深拷贝,浅拷贝的博客,最近js写的比较多, 所以也来玩玩js的对象拷贝. 下面是维基百科对深浅拷贝的解释: 浅拷贝 One method of copying an object is ...
- JavaScript的深拷贝和浅拷贝总结
深拷贝和浅拷贝 深拷贝:拷贝实例:浅拷贝:拷贝引用(原对象). 说深拷贝和浅拷贝之前,我先去了解了下高程书上的JavaScript的变量类型: 基本类型:undefined.null.Boolean. ...
- JavaScript的深拷贝和浅拷贝
一.数据类型 数据分为基本数据类型(String, Number, Boolean, Null, Undefined,Symbol)和对象数据类型.. 1.基本数据类型的特点:直接存储在栈(stack ...
- JavaScript的深拷贝与浅拷贝
深拷贝和浅拷贝是在面试中经常遇到的问题.今天在这里总结一下. 深拷贝与浅拷贝的问题,涉及到JavaScript的变量类型,先来说说变量的类型,变量类型包括基本类型和引用类型. 基本类型:Undefin ...
- 详解javascript的深拷贝与浅拷贝
1. 认识深拷贝和浅拷贝 javascript中一般有按值传递和按引用传递两种复制,按值传递的是基本数据类型(Number,String,Boolean,Null,Undefined),一般存放于内存 ...
- JavaScript之深拷贝和浅拷贝
前言 工作中会经常遇到操作数组.对象的情况,你肯定会将原数组.对象进行‘备份’当真正对其操作时发现备份的也发生改变,此时你一脸懵逼,到时是为啥,不是已经备份了么,怎么备份的数组.对象也会发生变化.如果 ...
- javaScript深拷贝和浅拷贝简单梳理
在了解深拷贝和浅拷贝之前,我们先梳理一下: JavaScript中,分为基本数据类型(原始值)和复杂类型(对象),同时它们各自的数据类型细分下又有好几种数据类型 基本数据类型 数字Number 字符串 ...
- 读懂javascript深拷贝与浅拷贝
1. 认识深拷贝和浅拷贝 javascript中一般有按值传递和按引用传递两种复制,按值传递的是基本数据类型(Number,String,Boolean,Null,Undefined),一般存放于内存 ...
随机推荐
- 修改git log中的Date格式
默认的git log查看日志显示的格式如下: Date: Thu Aug 16 17:44:32 2018 +0800 说实话,真不太喜欢这种日期格式还是换成数值比较舒服一点.git bash中使 ...
- Harbor高可用
项目需求: 实现Harbor的HTTPS高可用,由于Harbor 服务器配置不高,直接做HTTPS对上传下载镜像时,若docker客户端多时,会非常慢,为了提高harbor的效率,采用以下方式来解决. ...
- pytesseract.pytesseract.TesseractError: (1, 'Error opening data file /usr/local/share/tessdata/chi_sim.traineddata Please make sure the TESSDATA_PREFIX environment variable is set to your "tessdata"
pytesseract.pytesseract.TesseractError: (1, 'Error opening data file /usr/local/share/tessdata/chi_s ...
- 使用hdfs-mount挂载HDFS
目录 1.特性(计划)简介 2.构建程序 3.使用hdfs-mount挂载HDFS hdfs-mount是一个将HDFS挂载为本地Linux文件系统的工具,使用go语言开发,不依赖libdfs和jav ...
- linux剪贴板
ubuntu下的用户可以只用apt-get来安装: `sudo apt-get install xclip ` 其他发行版的用户可以选择自己的安装方式,也可以用源码编译安装,xclip项目的主页是:h ...
- Spring-boot +Shiro 导致事务无效
今天在开发过程中,遇到一个情况,就是事务事务,同项目的别的service都在事务中,可以就是有一个事务失效. 排除了各种情况 1.检查数据库的引擎是否是innoDB 2.方法是否为public 3.这 ...
- aardio类的例子
论坛里面相关资料太少,这里贴一下 库需要在工程的lib目录下,在ide里面就是用户库目录,比如 my_lib namespace my_lib{ import console class MyLibC ...
- 【GMT43智能液晶模块】例程十五:LAN_TCPC实验——以太网数据传输
源代码下载链接: 链接:https://pan.baidu.com/s/1bFX8_UpUlML29oqoDGaw5g提取码:mrf5 复制这段内容后打开百度网盘手机App,操作更方便哦 GMT43购 ...
- vue aes
npm install crypto-js import CryptoJS from "crypto-js/crypto-js"; const KEY = CryptoJS.enc ...
- Qt编写数据可视化大屏界面电子看板系统
一.前言 目前大屏大数据可视化UI这块非常火,趁热也用Qt来实现一个,Qt这个一站式超大型GUI超市,没有什么他做不了的,大屏电子看板当然也不在话下,有了QSS和QPainter这两个无敌的工具组合, ...