深拷贝与浅拷贝
在前端js里面的数据类型分为两大类:
1.基本数据类型(数据传递:值拷贝)
var a = 12; var b = a; // 赋值操作,是把 a 地址里面对应的值赋值给了 变量b 所对应的地址空间。 b = 24; a; // 不会受到影响 数据传递:值拷贝
2.复合数据类型(引用数据类型)
var obj = {id: 1, username: ‘andy‘, todos: [‘吃饭‘, ‘睡觉‘]}; // 复合数据类型 var xiaoming = obj; // 复合数据类型,地址的拷贝,现在 xiaoming 变量 和 obj 变量,同一个地址空间 // 好处:节省内存空间。 // 弊端:数据之间彼此受到影响。(存在在风险) xiaoming.username = ‘xiaoming‘; // xiaoming 变量 console.log(xiaoming); // xiaoming // 隐患 console.log(obj.username); // xiaoming
针对这种问题,我们把上面的这种现象叫做:浅拷贝。如果要解决这种问题,我们需要使用深拷贝进行实现:把复合数据类型(对象),将对象的key和value换成基本数据类型复制拷贝。
var tmp = {}; function copy( source ){ for(var attr in source ){ if( typeof source[attr] === ‘object‘ || typeof source[attr] === ‘array‘){ copy(source[attr]); }else{ // 基本的数据类型的拷贝 tmp[attr] = source[attr]; } } }
根据案例,递归代码(深拷贝:值拷贝),程序复杂不好理解,不好书写,并且存在性能问题,函数的使用,都需要开启内存空间,因此,减少递归的使用。
var obj = {id: 1, username: ‘andy‘, todos: [‘吃饭‘, ‘睡觉‘]} var xiaoming = JSON.parse( JSON.stringify(obj) ); 先把对象转化成字符串,在转化成Javascript对象
以上 虽然实现深拷贝,并且性能较好,但是存在一个问题:这种不能拷贝对象里面的方法,如果对象里面出现了方法,在使用JSON.stringify把方法丢失
es6中也存在一种拷贝方式,下例:
var obj = {id:1, name: ‘andy‘}; // Object.assgin 把多个参数进行合并,返回一个新的对象 var xiaoming = Object.assign({}, obj); xiaoming.name = ‘xiaoming‘; console.log(xiaoming.name); //xiaoming console.log(obj.name);// andy
但是这种拷贝存在弊端:1.浏览器兼容的问题 2.只实现第一层的深拷贝,其他的都不是深拷贝,只是浅拷贝。例如:
var obj = {id:1, name: ‘andy‘, todos: [‘eat‘, ‘sleep‘]}; // Object.assgin 把多个参数进行合并,返回一个新的对象 // Object.assgin 只实现一层的拷贝,如果对象的属性的值还是一个复合数据类型,完成的地址的引用(带来隐患) var xiaoming = Object.assign({}, obj); xiaoming.todos.push(‘dadoudou‘); xiaoming.name = ‘xiaoming‘; console.log(xiaoming.todos); // [ ‘eat‘, ‘sleep‘, ‘dadoudou‘ ] console.log(obj.todos); // 是否受到影响? 是 [ ‘eat‘, ‘sleep‘, ‘dadoudou‘ ]
如何解决这种深拷贝的问题呢?如何如何解决这种浅拷贝带来的性能问题和JSON.parse( JSON.stringify(obj) )代表的方法丢失问题?
我们可以采取第三方的库来完成 深拷贝 如: loadsh.js 。 immutable.js 。underscrejs 。
immutable 简介
Immutable Data 就是一旦创建,就不能再被更改的数据。对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。Immutable 实现的原理是 Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了Structural Sharing(结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。
参考资料:
https://www.jianshu.com/p/0fa8c7456c15
https://github.com/immutable-js/immutable-js
常见的数据类型和 api
https://segmentfault.com/a/1190000010676878?utm_source=tag-newest
1. List: 有序索引集,类似JavaScript中的Array。
2. Map: 无序索引集(hash key-value键值对),类似JavaScript中的Object。
3. Set: 没有重复值的集合。(数学上的集合)(集合三大特性:1. 无序性 2. 确定性(薛定谔的猫) 3. 唯一性)
为什么 react要使用immutable.js?
https://juejin.im/post/5d9f27666fb9a04e247c8ded
原文地址:https://www.cnblogs.com/hudunyu/p/11657255.html