javascript对象的浅拷贝、深拷贝和Object.assign方法浅析
对象的浅拷贝:
浅拷贝是对象共用一个内存地址,对象的变化相互影响。比如常见的赋值引用就是浅拷贝:
let srcObj = {'name': 'lilei', 'age': '20'};
let copyObj = srcObj;
copyObj.age = '22';
console.log('srcObj', srcObj); // srcObj { name: 'lilei', age: '22' }
console.log('copyObj', copyObj); // copyObj { name: 'lilei', age: '22' }
对象的深拷贝:
简单理解深拷贝是将对象放到一个新的内存中,两个对象的改变不会相互影响。
Object.assign()
MDN上这样介绍Object.assign(),'Object.assign() 方法用于将所有可枚举的属性的值从一个或多个源对象复制到目标对象。它将返回目标对象',好吧,并看不出是深拷贝还是浅拷贝,我们来测试一下
let srcObj = {'name': 'lilei', 'age': '20'};
let copyObj2 = Object.assign({}, srcObj, {'age': '21'});
copyObj2.age = '23';
console.log('srcObj', srcObj); //{ name: 'lilei', age: '22' }
看起来好像是深拷贝了,那其实这里let copyObj2 = Object.assign({}, srcObj, {'age': '21'});
我们把srcObj 给了一个新的空对象。同样目标对象为 {},我们再来测试下:
srcObj = {'name': '明', grade: {'chi': '50', 'eng': '50'} };
copyObj2 = Object.assign({}, srcObj);
copyObj2.name = '红';
copyObj2.grade.chi = '60';
console.log('新 objec srcObj', srcObj); // { name: '明', grade: { chi: '60', eng: '50' } }
从例子中可以看出,改变复制对象的name 和 grade.chi ,源对象的name没有变化,但是grade.chi却被改变了。因此我们可以看出Object.assign()拷贝的只是属性值,假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。
也就是说,对于Object.assign()而言, 如果对象的属性值为简单类型(string, number),通过Object.assign({},srcObj);
得到的新对象为‘深拷贝’;如果属性值为对象或其它引用类型,那对于这个对象而言其实是浅拷贝的。这是Object.assign()特别值得注意的地方。
多说一句,Object.assign({}, src1, src2);
对于scr1和src2之间相同的属性是直接覆盖的,如果属性值为对象,是不会对对象之间的属性进行合并的。
深拷贝的实现
有很多第三方库实现了对象的深拷贝,比如常见的 Jquery 和 underscore ,比较未来的 lodash,实现源码还没仔细分析,分析之后再来补充。
不过,如果你没有引入这些库,对于深拷贝还有一个简单的方法实现
JSON.parse() 和 JSON.stringify()
JSON.parse() 和 JSON.stringify() 算是对 深拷贝的一个无脑实现,看例子:
srcObj = {'name': '明', grade: {'chi': '50', 'eng': '50'} };
// copyObj2 = Object.assign({}, srcObj);
copyObj2 = JSON.parse(JSON.stringify(srcObj));
copyObj2.name = '红';
copyObj2.grade.chi = '60';
console.log('JSON srcObj', srcObj); // { name: '明', grade: { chi: '50', eng: '50' } }
可以看到改变copyObj2并没有改变原始对象,实现了基本的深拷贝。
但是用JSON.parse()和JSON.stringify()会有一个问题。
JSON.parse()和JSON.stringify()能正确处理的对象只有Number、String、Array等能够被json表示的数据结构,因此函数这种不能被json表示的类型将不能被正确处理。比如
srcObj = {'name': '明', grade: {'chi': '50', 'eng': '50'},'hello': function() {console.log('hello')}};
// copyObj2 = Object.assign({}, srcObj);
copyObj2 = JSON.parse(JSON.stringify(srcObj));
copyObj2.name = '红';
copyObj2.grade.chi = '60';
console.log('JSON srcObj', copyObj2); //{ name: '红', grade: { chi: '60', eng: '50' } }
可以看出,经过转换之后,function丢失了,因此JSON.parse()和JSON.stringify()还是需要谨慎使用。
后续再补充深拷贝实现思想。。。。
数组的深拷贝和浅拷贝
最后在补充一点数组的深拷贝和浅拷贝,同对象一样数组的浅拷贝也是改变其中一个会相互影响,比如:
let srcArr = [1, 2, 3];
let copyArr = srcArr;
copyArr[0] = '0';
console.log('srcArr', srcArr); // ['0', 2, 3]
但是数组的深拷贝方法要相对简单一些可以理解为数组方法中那些会改变原数组的方法,比如
- concat
- slice
- es6 的Array.from
javascript对象的浅拷贝、深拷贝和Object.assign方法浅析相关推荐
- Object.assign() 方法的使用详解
Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象.它将返回目标对象. 注意: 会改变源对象 语法: Object.assign(target, ...sou ...
- JavaScript 复制对象与Object.assign方法无法实现深复制
在JavaScript这门语言中,数据类型分为两大类:基本数据类型和复杂数据类型.基本数据类型包括Number.Boolean.String.Null.String.Symbol(ES6 新增),而复 ...
- JavaScript中的Object.assign()方法
目录 介绍 什么是Object.assign()? JavaScript可枚举属性 语法和参数 您可以使用Object.assign()方法做什么? 合并对象 克隆对象 关于Object.assign ...
- es6 Object.assign()方法
Object.assign()方法 基本用法 Object.assign()方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target). const target = ...
- Object.assign()方法
1.对象的扩展 ES6中,对象的属性和方法可简写:对象的属性值可不写,前提是属性名已经声明: var name = "zhangsan";var password = " ...
- Object.assign方法的使用和splice方法用法
一.基本语法 Object.assign(target, ...sources) 二.基本概念 Object.assign方法用来将源对象(source)的所有可枚举属性,复制到目标对象(target ...
- Object.assign()方法的用法
1.合并多个对象 2.克隆对象(浅): 3.为对象添加多个方法 定义方法: insertRprm(data) {let params = Object.assign({}, {pagename: 'n ...
- ES6 深拷贝_你别自以为是:ES6误区 之 Object.assign()、const
文/北妈 阅读本文需要 2.3分钟 一 很久没发技术文,今天北妈在新开一个技术系列:"别自以为是,1分钟走出JS常见误区",里面我会每期挑选几个常见基础属性,讲一讲里面最容易被人忽 ...
- JavaScript 对象合并
JavaScript 中有多种方法可以合并对象. 1.使用 Object.assign() 方法: 它可以将一个或多个对象的属性复制到目标对象中.例如: const obj1 = { a: 1, b: ...
- javaScript对象的深拷贝和浅拷贝
深拷贝和浅拷贝定义 浅拷贝:只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做浅拷贝(浅复制).浅拷贝只复制指向某个对象的指针(引用地址),而不复制对象本身,新旧对象还 ...
最新文章
- 微信小程序和vue双向绑定哪里不一样_vue和微信小程序的区别、比较
- 税前2万4,到手1万4,年终奖扣税方式1月1日起施行~
- shuffleNetv2 测试
- 深入浅出SharePoint——取消Workflow实例
- 05-iOS蓝牙开发总结
- 20170227玩呗娱乐
- js布尔类型+数字判断_C ++中的布尔数据类型
- 网站流量日志分析系统笔记(Hadoop大数据技术原理与应用)
- (pythonQQ群管理)通过selenium 自动批量删除QQ群成员
- html表格固定右侧列,jQuery锁定表头和固定列插件FixedTable
- toolchain安装教程支持_riscv-gnu-toolchain的安装经历
- bat脚本修改文件内容
- Python 时间标准化
- Ubuntu18.04系统安装及深度学习框架搭建
- ttyS、tty,console和pty
- 以前不懂事现在只想搞钱,从0-1搭建一个树莓派小车
- 嵌入式LinuxC--指针与数组
- 华为,小米开关控制设置指南总自动弹出
- c语言中 amp amp 是位运算符吗,c语言位运算符(c语言位运算符的用法举例)
- Qt扫盲-QMake 使用概述