前端随心记---------深拷贝与浅拷贝

Posted hudunyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端随心记---------深拷贝与浅拷贝相关的知识,希望对你有一定的参考价值。

 深拷贝与浅拷贝

  在前端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

 

以上是关于前端随心记---------深拷贝与浅拷贝的主要内容,如果未能解决你的问题,请参考以下文章

Java 深拷贝与浅拷贝概念与代码实现

通过项目实战学习:深拷贝与浅拷贝的内涵,实现深拷贝的几种方法,深拷贝解决项目异常bug

iOS开发——深拷贝与浅拷贝详解

iOS之深拷贝与浅拷贝

python 的深拷贝与浅拷贝

JavaScript深拷贝与浅拷贝