ES6深拷贝与浅拷贝
小感在前
React学习与开发过程要经历一个相当长的准备阶段,此前看阮一峰老师的文章中,他就特别提到这一点。但是,由于React框架或者说是一种优秀的前端架构实在太诱人,所以,掌握这项技术所涉及的技术栈过程中经历的任何苦恼都是值得的。在还没有全面掌握这项技术的不断探索过程中,如果包括后端的一部分在内(例如Node.js和Express等,还有一些数据库及API知识),至少要有几十部分,仅限于核心的算起来也有十多项吧。
作为一个基础部分,ES6势在必学。此前,我曾得意于自己已经掌握了一定程度的JS知识,但是在匆读阮老师的《ES6标准入门》一书后才感觉自己落后许多了。同时,在阅读本书的过程中,也发现:这本书或者整个ES6,的确是为着眼于将来的“一统前后端”的大项目作准备的,因此,重复地专门学习这个语言是没有必要的。这是一本案头书,需要什么时再读什么更合适。
本文罗列的就是在本人在学习Redux过程中在遭遇到JS的深浅拷贝过程中总结的相关内容。太匆忙与粗略,仅供同学们参考。
JavaScript 中变量的赋值
结论:JavaScript中变量的赋值分为「传值」与「传址」。
基本数据类型的赋值,就是「传值」;而引用类型变量赋值,实际上是「传址」。
基本数据类型变量的赋值、比较,只是值的赋值和比较,也即栈内存中的数据的拷贝和比较,参见如下代码:
var num1 = 123;
var num2 = 123;
var num3 = num1;
num1 === num2; // true
num1 === num3; // true
num1 = 456;
num1 === num2; // false
num1 === num3; // false
引用数据类型变量的赋值、比较,只是存于栈内存中的堆内存地址的拷贝、比较,参加如下代码:
var arr1 = [1, 2, 3];
var arr2 = [1, 2, 3];
var arr3 = arr1;
arr1 === arr2; // false
arr1 === arr3; // true
arr1 = [1, 2, 3];
arr1 === arr2; // false
arr1 === arr3; // false
JavaScript 中变量的拷贝
JavaScript中的拷贝区分为「浅拷贝」与「深拷贝」。
浅拷贝
浅拷贝只会将对象的各个属性进行依次复制,并不会进行递归复制,也就是说只会进行赋值目标对象的第一层属性。
对于目标对象第一层为基本数据类型的数据,就是直接赋值,即「传值」;而对于目标对象第一层为引用数据类型的数据,就是直接赋存于栈内存中的堆内存地址,即「传址」。
深拷贝
深拷贝不同于浅拷贝,它不但拷贝目标对象的第一层属性,而且还递归拷贝目标对象的所有属性。
一般来说,在JavaScript中考虑复合类型的深层复制的时候,往往就是指对于 Date 、Object 与 Array 这三个复合类型的处理。我们能想到的最常用的方法就是先创建一个空的新对象,然后递归遍历旧对象,直到发现基础类型的子节点才赋予到新对象对应的位置。
不过这种方法会存在一个问题,就是 JavaScript 中存在着神奇的原型机制,并且这个原型会在遍历的时候出现,然后需要考虑原型应不应该被赋予给新对象。那么在遍历的过程中,我们可以考虑使用 hasOwnProperty 方法来判断是否过滤掉那些继承自原型链上的属性。
Object.assign
Object.assign 方法可以把 任意多个的源对象所拥有的自身可枚举属性 拷贝给目标对象,然后返回目标对象。
注意:
对于访问器属性,该方法会执行那个访问器属性的 getter 函数,然后把得到的值拷贝给目标对象,如果你想拷贝访问器属性本身,请使用 Object.getOwnPropertyDescriptor() 和 Object.defineProperties() 方法;
字符串类型和 symbol 类型的属性都会被拷贝;
在属性拷贝过程中可能会产生异常,比如目标对象的某个只读属性和源对象的某个属性同名,这时该方法会抛出一个 TypeError 异常,拷贝过程中断,已经拷贝成功的属性不会受到影响,还未拷贝的属性将不会再被拷贝;
该方法会跳过那些值为 null 或 undefined 的源对象;
利用 JSON 进行忽略原型链的深拷贝
var dest = JSON.parse(JSON.stringify(target));
同样的它也有缺点:
该方法会忽略掉值为 undefined 的属性以及函数表达式,但不会忽略值为 null 的属性。
借助于Lodash 的 merge 方法
在Redux开发中的一个应用是借助于Lodash 的 merge 方法可以实现深拷贝,达到管理范式化数据的目的,示例代码如下:
import merge from "lodash/object/merge";function commentsById(state = {}, action) {switch(action.type) {default : {if(action.entities && action.entities.comments) {return merge({}, state, action.entities.comments.byId);}return state;}}
}
存在大量深拷贝需求时借助immutable库
实际上,即使我们知道了如何在各种情况下进行深拷贝,我们也仍然面临一些问题: 深拷贝实际上是很消耗性能的。(我们可能只是希望改变新数组里的其中一个元素的时候不影响原数组,但却被迫要把整个原数组都拷贝一遍,这不是一种浪费吗?)所以,当你的项目里有大量深拷贝需求的时候,性能就可能形成了一个制约的瓶颈了。
immutable的作用是通过immutable引入的一套API,实现:
1.在改变新的数组(对象)的时候,不改变原数组(对象)
2.在大量深拷贝操作中显著地减少性能消耗
参考代码:
const { Map } = require('immutable')
const map1 = Map({ a: 1, b: 2, c: 3 })
const map2 = map1.set('b', 50)
map1.get('b') // 2
map2.get('b') // 50
尽量保持数据设计的扁平化与科学设计Reducer
在React+Redux开发中,经常要遇到不可变数据的更新问题。复杂情形中,往往需要复制嵌套数据的所有层级。但不幸的是,正确地使用不变的更新去深度嵌套状态的过程很容易变得冗长难读。 更新 ate.first.second[someId].fourth 的示例(http://www.redux.org.cn/docs/recipes/reducers/ImmutableUpdatePatterns.html)大概如下所示:
function updateVeryNestedField(state, action) {return {....state,first : {...state.first,second : {...state.first.second,[action.someId] : {...state.first.second[action.someId],fourth : action.someValue}}}}
}
显然,每一层嵌套使得阅读更加困难,并给了更多犯错的机会。这是其中一个原因,鼓励你保持状态扁平,尽可能构建小巧而灵活的Reducer。
引用
1,https://juejin.im/post/5acc7e606fb9a028c67609f7
2,https://zhuanlan.zhihu.com/p/28508795
3,http://www.zsoltnagy.eu/cloning-objects-in-javascript/
4,http://www.cnblogs.com/penghuwan/p/7359026.html
5,https://blog.csdn.net/github_38524608/article/details/78812761
6,https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Spread_syntax
7,http://www.redux.org.cn/docs/recipes/reducers/UpdatingNormalizedData.html
相关文章:

hung-yi lee_p22_无监督学习:词嵌入
文章目录原视频地址:添加链接描述输入是一个词 输出是一个向量 整个过程无监督 用来训练的是一堆文章 精神: 根据一个词汇的上下文来理解它 具体: 1.count based 两个词经常一起出现,认为它们是相似的 2.prediction-based 给神经…

用vs2010打开使用vs2013升级后的WP工程
项目在win7vs2010的环境中建立的,后来在win8.1vs2013的环境下修改和完善: 但是所有功能实现后发现wp7项目在使用vs2013打开后因为单向升级的原因,项目只能被编译为wp8项目(win8.1vs2013无法安装wp7的sdk,提示不兼容&am…

神州6号发射成功了--庆祝一下
转载于:https://www.cnblogs.com/ccBoy/archive/2005/10/12/253268.html

android保持服务不休眠(持续运行)以及唤醒屏幕的方法
假设有这样一个应用场景,一个服务一直在默默的工作(比如即时地获取服务器的消息),即使在屏幕已经因为长时间无操作而关闭,或者用户按了电源键让屏幕关闭,手机进入休眠状态,他必须依然在工作中。…

三类常见软件质量(Quality Attribute)属性的通俗解释
外部质量 用户关心 正确性,最最基本的质量属性,对应功能需求,其他QA多对应非功能需求。健壮性,在异常情况下正常运行的能力。 包含容错能力和恢复能力。恢复没有容错健壮。可靠性,用平均无bug运行时间与平均bug修复时…

winform动态的文字效果
效果图如下 private void Form1_Load(object sender, EventArgs e){Graphics Car_Paint panel1.CreateGraphics();//实例化绘图对象string Car_Str "青岛**软件公司";//定义要绘制的动态文字Character character new Character();//实例化自定义类对象character.D…

使用Mycat构建MySQL读写分离、主从复制、主从高可用
数据库读写分离对于大型系统或者访问量很高的互联网应用来说,是必不可少的一个重要功能。 从数据库的角度来说,对于大多数应用来说,从集中到分布,最基本的一个需求不是数据存储的瓶颈,而是在于计算的瓶颈,…

SharePoint的Reporting Service Viewer Web Part
今天本来打算做一个专门用于Reporting Service报表浏览的SharePoint web part,记得在Reporting Service 2000下有一个viewer的Sample,就想找来参考一下,谁知在C:\Program Files\Microsoft SQL Server\90\Tools\Reporting Services\SharePoint…

7个面向对象常用原则的中英文名、别名、定义及显著特点
单一职责原则 英文名:Single Responsibility Principle(SRP) 别名:无 定义1:一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中 定义2:就一个类而言,应该仅有一个引起它变化的原因 开闭原则…

常见的“公共标志和说明”英文表达
1、Business Hours 营业时间 2、Office Hours 办公时间 3、Entrance 入口 4、Exit 出口 5、Push 推 6、Pull 拉 7、Shut 此路不通 8、On 打开 ( 放) 9、Off 关 10、Open 营业 11、Pause 暂停 12、Stop 关闭 13、Closed 下班 14、Menu 菜…

【T-SQL】基础——表别名
Som有时候我们需要为表设置别名,这样就可以方便的修改表。 如果在SSMS中,可以点击 Query-> SQL CMD mode --Set Alisa for the table:setvar tablename "[RetailDataWarehouse].[dbo].[FactUnit]" Select ExternalOrderId,COUNT(DISTINCT(R…

数据挖掘的实现流程
文章目录1.数据、信息与知识2.数据挖掘实现流程概览图3.数据准备(step 1)4.数据挖掘(step 2)5.模型的评估解释(step 3)6.知识运用(step 4)7.小结1.数据、信息与知识 2.数据挖掘实现流程概览图 这里提供两张图,以下讲解基于第一张图。 3.数据准备(step 1) Knowl…

设计模式:备忘录模式??
定 义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。 这样以后就可以将该对象恢复到原先保存的状态。 结构图: Originator(发起人):负责创建一个备忘录(Memento)ÿ…

如何用Python批量提取PDF文本内容?
本文为你展示,如何用Python把许多PDF文件的文本内容批量提取出来,并且整理存储到数据框中,以便于后续的数据分析。 问题 最近,读者们在后台的留言,愈发五花八门了。 写了几篇关于自然语言处理的文章后,一种…

常用的3种注入方式
构造注入 指通过构造函数来传入具体类的对象设值注入(Setter注入) 指通过Setter方法来传入具体类的对象接口注入 指通过在接口中声明的业务方法传入具体类的对象

WebService客户端添加SOAPHeader信息
WebService客户端添加SOAPHeader信息 通过JAXBContext创建Marshaller对头信息进行解析为dom,获取WSBindingProvider,使用Headers.creat()创建soap的Header元素; 另外就是:将user转换为dom是为了不在有wsdl生成的LicenceInfo类中增…

MATLAB 向量
MATLAB 向量: 1、MATLAB 行向量: 创建行向量括在方括号中的元素的集合,用空格或逗号分隔的元素。 2、MATLAB 列向量: 创建列向量括在方括号中的元素的集合,使用分号来分隔的元素。 3、

Wiki为什么会流行
我来开题,老段补充一下,嘿嘿。。。Wiki的优点:版本管理和版本比较多作者,多编辑的协作简洁Wiki的缺点(或者第一次用不是很习惯的地方): 非所见即所得需要学习一下简单的语法文章的分类好像不是很地道所有的链接基本是自…

hung-yi lee_p18_图神经网络(cont.)
文章目录1. 简介2. 怎么把图喂到神经网络里面呢3. 为什么需要GNN4. 训练GNN遇到的问题5. 后面的内容安排6. GNN要做的事,常用数据集和基准7. 第一种实现GNN的方法(Spatial-based GNN)7.1 NN4G7.2 DCNN7.3 DGC7.4 MoNET番外:聚集的几种方法7.5 GAT7.5 GIN…

SQL Server2008附加数据库之后显示为只读
SQL Server2008附加数据库之后显示为只读时解决方法 啰嗦的话就不多说了,直入主题吧! 方案一: 碰到这中情况一般是使用的sa账户登录的,只要改为Windows身份验证,再附加数据库即可搞定。 方案二: 使用sa登录…

java maven项目使用sonar审核代码
为什么80%的码农都做不了架构师?>>> 一、pom增加插件 <plugin><groupId>org.sonarsource.scanner.maven</groupId><artifactId>sonar-maven-plugin</artifactId><version>3.1.1</version> </plugin> 二…

ERP成功全球实施十大成功案例
、美铝公司(Alcoa) 公司简介 美铝公司创办于19世纪80年代中期,目前是世界最大的氧化铝、电解铝和铝加工产品的生产商,活跃于包括基础研究和开发、技术及回收利用等铝工业的所有主要领域。美铝产品应用于航空航天、汽车、包装、建筑…

CentOS安装Oracle全过程
1.准备工作 (1)安装Java环境 (2)增大SWAP空间 1.1 切换为root用户 1.2 dd if/dev/zero of/home/swap bs1024 count204800 1.3 /sbin/mkswap /home/swap 1.4 /sbin/swapon /home/swap 1.5 free -m 1.6 vi /etc/fstab 添加 /home/…

Hide the common top menu in Ubuntu 12.04
隐藏:1、sudo apt-get autoremove appmenu-gtk appmenu-gtk3 appmenu-qt2、reboot恢复:1、sudo apt-get install appmenu-gtk appmenu-gtk3 appmenu-qt2、reboot转载于:https://www.cnblogs.com/wiessharling/p/3569616.html

在IBatisNet中使用存储过程
其实在IBatisNet中使用存储过程应该很简单了,应为IBatisNet本来就是基于Sql Mapping的。想着Npetshop中应该有例子看一下就行了,可是查了查map文件,发现没有,只要自己动手搞搞了。 在建立的测试数据库中建立一个简单的存储过程del…

人工智能时代,教育如何做人工智能的“弄潮儿”?
汇新杯新兴科技互联网创新大赛报名火热进行中 汇新杯大赛报名入口:https://www.chuangcheng.org.cn/4552016年人工智能火了,它被行业公认为是继互联网、移动互联网之后的又一重大机遇和挑战,并将成为各个领域的“水电煤”,成为行业…

centOS安装Java环境全过程
1.通过ssh将安装包从本地传到/usr/local文件夹下 2.解压安装包 tar -zxvf /usr/local/jdk-**** 3.给解压后的文件夹改名 mv /usr/local/jdk1.8.0_271 /usr/local/java 4.修改配置文件,配置环境变量 vi /etc/profile export JAVA_HOME/usr/local/java export PAT…

vue组件的传参练习
为什么80%的码农都做不了架构师?>>> 首先是父组件与子组件沟通 父组件告诉子组件,“嘿,孩子,我有话和你说” 组件A代码 <template><section><h1>这是组件</h1><test-B :chile-name"u…

Avayaの初体验
这个题目是不是给了你一种无法抗拒的吸引力并引起了你无限的幻想呢?一个名为Avaya的清纯少女……Stop!今天我要说的是电话交换机。说来惭愧,本来是个学通信的,到后来却不务正业搞了软件,到现在突然组织又需要我去搞Ava…

Git fetch和git pull的区别
原文:http://www.tech126.com/git-fetch-pull/ Git中从远程的分支获取最新的版本到本地有这样2个命令:1. git fetch:相当于是从远程获取最新版本到本地,不会自动merge git fetch origin master git log -p master..origin/mas…