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

深拷贝与浅拷贝

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

时间: 2024-11-09 03:52:09

前端随心记---------深拷贝与浅拷贝的相关文章

前端随心记---------vuejs流行的UI框架

一:Element element ui框架的按钮组件,这款由饿了么前端开源的UI框架,一经面世,就收获大量程序员的芳心.在github 上更是高达29.8k的star早已说明一切.用于开发PC端的页面还是绰绰有余的.如果说你是用vue开发者,却没用过element UI,那你肯定不是合格的vue开发者. 文档地址:http://element-ui.cn 二:iview iView 是一套基于 Vue.js 的开源 UI 组件库,主要服务于 PC 界面的中后台产品.使用单文件的 Vue 组件化

前端随心记(一)

前端 基础易错题(一) 案例一::介绍js原型链继承原理,以及prototype和--proto--的区别! 1.任何一个构造函数都有一个属性prototype叫做构造函数的原型,是一个对象,并且该对象默认情况下指向Object实例,constructor指向当前构造函数,--proto--指向Object.protopyte. 2.使用构造函数实例化的对象存在一个--proto--属性,指向当前构造函数的prototype. 3.当我们调用实例对象的属性和方法时,先在自身上面进行查找[自己身上

前端随心记---------React简介(1)

React 简介: React 是一个用于构建用户界面的 JAVASCRIPT 库. React 主要用于构建UI,很多人认为 React 是 MVC 中的 V(视图). React 起源于 Facebook 的内部项目,用来架设 Instagram 的网站,并于 2013 年 5 月开源. React 拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使用它. React诞生的原因 主要是当时市面上的这些框架都无法满足 facebook 公司的业务需求 (1. 数据量很大,数据不好管理

前端随心记---------vue3.0终于来了,作者已公布源码

Vue3.0 何去何从? 就在国庆的第五天,10月5日凌晨,web前端开发框架Vuejs的作者:尤雨溪在微博宣布Vue3.0版本终于要面正式推出了!  其实,在11月14日-16日于多伦多举办的 VueConf TO 2018 大会上,尤雨溪发表了名为 “ Vue 3.0 Updates ” 的主题演讲,对 Vue 3.0 的更新计划.方向进行了详细阐述. 1.更快 Virtual DOM 完全重写,mounting & patching 提速 100% : 更多编译时(compile-time

前端随心记---------前海面试汇总

react里面:state和prop的区别?setState为什么是异步的?组件传值有几种方式? 答:1.prop用于定义外部接口,state用于记录内部状态.2.prop的赋值在外部使用组件时,state的赋值在组建内部.3.组件不应该改变prop的值,但是state的存在目的是让组件来改变. 2.setState异步更新状态使得并发更新组件成为可能. 资料:https://segmentfault.com/a/1190000013040438?utm_source=tag-newest 3.

前端随心记---------webpack管理工具

webpack: 官网:https://www.webpackjs.com/ 由来: 1.开发的时候,我们写的代码是有注释,有空格(文件比较大)在开发环境中注释有意义的,但是在生产环境中,注释是没有意义的.代码应该是尽可能压缩的足够小(网络请求)如果我们没有借助一些其他工具的时候,我们需要手工的把 xxx.js 转换 xxx.mini.js 文件.(文件美化) 2.我们的js在发展的过程中,出现很多的新特性,例如 es6 箭头函数.class 语法糖,Promise等.这些新的特性在不做处理的时

前端随心记---------Axios/fetch/ajax的区别

一.jQuery  ajax $.ajax({ type: 'POST', url: url, data: data, dataType: dataType, success: function () {}, error: function () {} }); 传统 Ajax 指的是 XMLHttpRequest(XHR), 最早出现的发送后端请求技术,隶属于原始js中,核心使用XMLHttpRequest对象,多个请求之间如果有先后关系的话,就会出现回调地狱. JQuery ajax 是对原生

前端随心记---------Ajax,Comet,Websocket

从WebScoket中我们了解到Ajax的轮询问题,WebScoket协议中服务器和客户端只要进行一次握手,就能创建一条通道实现数据的相互传送.而Ajax轮询,在特定的时间间隔内向服务器发送请求,以达到对数据的推送,这样导致浪费了很多无谓的网络带宽,因此产生疑问:为了达到高效且资源利用最大化的角度,WebScoket为什么没有淘汰定时轮询这种机制呢? 什么是Websocket Websocket是HTML5中提出的新的协议,注意,这里是协议,可以实现客户端与服务器端的通信,实现服务器的推送功能.

前端随心记---------HTML5+CSS系列2.0

超链接的应用: 语法:    <a href="连接地址" title="提示信息" target=”属性值”> 链接文本/图片</a> 属性(名):target:页面打开方式 默认属性值:_self. I当前窗口 属性值:_blank 新窗口打开  <a href="#">空链接</a>  HTML标记的语法是 1.双标记: <标记(签)名称 属性1名="属性1值" 属性