浅谈Javascript 浅拷贝和深拷贝的理解
javascript中存储对象都是存地址的。
浅拷贝:浅拷贝是都指向同一块内存区块,浅拷贝共用同一内存地址,你改值我也变。如果拷贝的对象里面的值是一个对象或者数组,它就是浅拷贝,拷贝的知识引用地址。 js的Object.assign,jquery的extend方法都是浅拷贝,一般的等号赋值也是浅拷贝 。
上面vue里面的两个写法也是浅拷贝,具体地址为 https://cn.vuejs.org/v2/guide/list.html
深拷贝:深拷贝则是另外开辟了一块区域,深拷贝是互不影响,你改值我也不变。angular里面的 angular.copy 是深拷贝。
下面实例也可以看出这一点:
- // 浅拷贝
- const a = {t: 1, p: 'gg'};
- const b = a;
- b.t = 3;
- console.log(a); // {t: 3, p: 'gg'}
- console.log(b); // {t: 3, p: 'gg'}
- //深拷贝
- const c = {t: 1, p: 'gg'};
- const d = deepCopy(c);
- d.t = 3;
- console.log(c); // {t: 1, p: 'gg'}
- console.log(d); // {t: 3, p: 'gg'}
- //浅拷贝 es6 扩展运算符
- let a = [,,,,];
- let b = a; // 相当于copy
- a.push();
- console.log(a); // [14, 12, 54, 33, 22, 44]
- console.log(b); // [14, 12, 54, 33, 22, 44]
- //深拷贝
- let a = [,,,,];
- let b = [...a];
- a.push();
- console.log(a); // [14, 12, 54, 33, 22, 44]
- console.log(b); // [14, 12, 54, 33, 22]
可以明显看出,浅拷贝在改变其中一个值时,会导致其他也一起改变,而深拷贝不会。
Object.assign() ————深拷贝神器,这个方法就是用来拷贝一个对象的,通常做法就是Object.assign({}, sourceObject, { key1: value1,key2: value2}) {}表示目标对象,会定义成一个空的{},sourceObjec就是源对象
- // Cloning an object
- var obj = { a: 1 };
- var copy = Object.assign({}, obj);
- console.log(copy); // { a: 1 }
- // Merging objects
- var o1 = { a: 1 };
- var o2 = { b: 2 };
- var o3 = { c: 3 };
- var obj = Object.assign(o1, o2, o3);
- console.log(obj); // { a: 1, b: 2, c: 3 }
- console.log(o1); // { a: 1, b: 2, c: 3 }, target object itself is changed.
- console.log(o2);//{b: 2} 源对象没有变
- console.log(o3);// {c: 3}
是不是很完美,又可以clone又可以merge。在我这种情况下,我觉得我的代码量又可以减少了,比如:
- const defaultOpt = {
- title: 'hello',
- name: 'oo',
- type: 'line'
- };
- // 原来可能需要这样
- const opt1 = deepCopy(a);
- opt1.title = 'opt1';
- opt1.type = 'bar';
- opt1.extra = 'extra'; // 额外增加配置
- // 现在只要这样
- const opt2 = Object.assign({}, a, {
- title: 'opt2',
- type: 'bar',
- extra: 'extra'
- });
- 注:它只对顶层属性做了赋值,完全没有继续做递归之类的把所有下一层的属性做深拷贝。意思就是是拷贝一层,没有拷贝多层。
- 一层
- {
- a: 1,
- b: 2,
- }
- 多层
- {
- a: 1,
- b: 2,
- c: {
- d: 4,
- e: {
- f: 6,
- g: 7
- }
- }
- }
- 实现深拷贝,遍历key
- function deepClone(obj){
- //判断obj是否为数组,如果是,初始化数组[],否则初始化对象{}
- let dcObj = Array.isArray(obj)?[]:{};
- if(obj && typeof obj==="object"){
- //循环
- for(key in obj){
- //判断对象是否有key属性
- if(obj.hasOwnProperty(key)){
- //判断ojb子元素是否为对象,如果是,递归复制
- if(obj[key]&&typeof obj[key] ==="object"){
- dcObj[key] = deepClone(obj[key]);
- }else{
- //如果不是,简单复制
- dcObj[key] = obj[key];
- }
- }
- }
- }
- return dcObj;
- };
- let t1 = {
- "a": 1,
- "b": 2,
- "c": {
- "d": 4,
- "e": {
- "f": 6,
- "g": 7
- }
- }
- };
- let t2=deepClone(t1);
- t1.a=6;
- console.log(t1);
- /*
- {
- "a": 6,
- "b": 2,
- "c": {
- "d": 4,
- "e": {
- "f": 6,
- "g": 7
- }
- }
- }
- */
- console.log(t2); //t1深拷贝给t2, b属性的值还是为2,没有改变,所以是深拷贝
- /*
- {
- "a": 1,
- "b": 2,
- "c": {
- "d": 4,
- "e": {
- "f": 6,
- "g": 7
- }
- }
- }
- */
参考:https://www.jianshu.com/p/a66050673663
浅谈Javascript 浅拷贝和深拷贝的理解的更多相关文章
- 浅谈C#浅拷贝和深拷贝
近来爱上一本书<编写高质量代码,改善C#程序的157个建议>,我想很多人都想编写高质量的代码,因为我们不仅仅是码农,更是一名程序员. 从今天开始,我将每天和大家分享这本书中的内容,并加上自 ...
- 浅谈java浅拷贝和深拷贝
前言:深拷贝和浅拷贝的区别是什么? 浅拷贝:被复制的对象的所有变量都含有原来对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之, 浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象.深拷 ...
- 浅谈Java中的深拷贝和浅拷贝(转载)
浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...
- 浅谈Java中的深拷贝和浅拷贝
转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...
- 浅谈JavaScript中的闭包
浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...
- 浅谈 JavaScript 编程语言的编码规范
对于熟悉 C/C++ 或 Java 语言的工程师来说,JavaScript 显得灵活,简单易懂,对代码的格式的要求也相对松散.很容易学习,并运用到自己的代码中.也正因为这样,JavaScript 的编 ...
- 浅谈javascript的原型及原型链
浅谈javascript的原型及原型链 这里,我们列出原型的几个概念,如下: prototype属性 [[prototype]] __proto__ prototype属性 只要创建了一个函数,就会为 ...
- 浅谈JavaScript中的正则表达式(适用初学者观看)
浅谈JavaScript中的正则表达式 1.什么是正则表达式(RegExp)? 官方定义: 正则表达式是一种特殊的字符串模式,用于匹配一组字符串,就好比用模具做产品,而正则就是这个模具,定义一种规则去 ...
- 浅谈javascript函数节流
浅谈javascript函数节流 什么是函数节流? 函数节流简单的来说就是不想让该函数在很短的时间内连续被调用,比如我们最常见的是窗口缩放的时候,经常会执行一些其他的操作函数,比如发一个ajax请求等 ...
随机推荐
- wordpress不同分类调用不同的模板
今天网友问ytkah:wordpress不同分类如何调用不同的模板.我们知道in_category() 函数可以通过分类别名或ID判断当前文章所属的分类,而且可以直接在循环(Loop)内部和外部使用. ...
- Java Excel 导入导出(二)
本文主要叙述定制导入模板——利用XML解析技术,确定模板样式. 1.确定模板列 2.定义标题(合并单元格) 3.定义列名 4.定义数据区域单元格样式 引入jar包: 一.预期格式类型 二.XML模板格 ...
- 2019阿里JVM组实习面经
面试质量非常高....非常高...高... 一面 自我介绍 看过hotspot哪些模块,模板解释器工作说一下,生成的native code放在哪,怎么处理safepoint的 说项目,实现了哪些字节码 ...
- apollo报:系统出错,请重试或联系系统负责人
说明:基于 docker 搭建的 apollo,创建项目后一直报系统出错,请重试或联系系统负责人错误. 项目人员列表一直空白: 经排查是数据库配置参数不匹配,由于自己的虚拟机 ip 为 192.168 ...
- MongoDB 聚合查询报错
1.Distinct聚合查询报错 db.users.distinct("uname") db.runCommand({"distinct":"user ...
- ESA2GJK1DH1K微信小程序篇: 测试微信小程序扫描Air202上面的二维码绑定设备,并通过MQTT控制设备
前言 一,微信小程序篇小程序下载(该功能为小程序篇基础功能源码) 实现功能概要 微信小程序通过扫描GPRS上的二维码,绑定GPRS设备.然后使用小程序通过GPRS远程控制开发板上的继电器, 远程显示单 ...
- 【BigData】Java基础_冒泡排序
1.实现需求 根据已经存在的数组,使用冒泡排序将数组中的元素排序后输出. 2.代码 package cn.test.logan.day02; /** * 冒泡排序在数组上的实现 * @author Q ...
- 提前体验让人"回归Windows怀抱"的Windows Terminal
前言 在一年一度的微软开发者大会Build 2019登场的Windows Terminal饱受好评,大家对其也是充满了兴趣和热情,程序员的朋友圈都被微软发布的最新终端 windows Terminal ...
- js操作表格、table、
js添加一行.删除一行 let str="<tr>" +"<td>"+a[1]+"</td>" +&qu ...
- ubuntu之路——day19.2 开源框架与迁移、CNN中的数据扩充
开源框架与迁移 上面介绍了一些已经取得很好成绩的CNN框架,我们可以直接从GitHub上下载这些神经网络的结构和已经在ImageNet等数据集上训练好的权重超参数. 在应用于我们自己的数据时. 1.如 ...