千锋教育-做有情怀、有良心、有品质的职业教育机构

手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

当前位置:首页  >  技术干货  > 不可变数据之Immutable

不可变数据之Immutable

来源:千锋教育
发布人:qyf
时间: 2022-09-15 15:01:27 1663225287

不可变数据之Immutable

  在讲不可变数据(Immutable Data)前,先说说可变数据(Mutable Data),在原生js中创建的数据都是可变的,如:

  var a = {qty:1}

  a.qty = 10;

  可能有小伙伴说,可以用const啊,const对基本数据类型还行,但对引用数据类型根本没辙,如

  const a = {qty:1}

  a.qty = 10;

  a.qty;// 10

  如果把对象a赋值给其它变量还会导致新的问题,如:

  const a = {qty:1}

  const b = a;

  a.qty = 10;

  b.qty;//10

  这时你会发现,修改了a,b的值也跟着改了,这其实是js采用引用赋值的方式来实现数据共享的,好处就是节省内存,但缺点也显而易见,稍微不注意就会导致改A坏B的棘手问题,在复杂的项目中,这种问题还不易排查,有诸多安全隐患。

  之前的做法是,利用深拷贝的方式来解决这个问题,虽然问题解决了,但又会引发新的问题:浪费内存,还有对一些需要频繁更新数据又有高性能要求的场景(如:React),深拷贝实则为一个不明智的操作,于是,Imutable.js的出现就是要解决这些开发痛点的。

  Immutable.js 由Facebook 工程师 Lee Byron 花费 3 年时间打造,在js中的引用赋值可以节省内存,但随着应用的不断复杂后,状态的改变往往会变成噩梦,通常的做法是复制数据来避免被修改,但这样又造成了CPU和内存的消耗,而Immutable利用结构共享可以很好地解决这些问题。

  不可变数据:Immutable Data

  Immutable Data 是一旦创建,就不能再被更改的数据。对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。Immutable 实现的原理是 Persistent Data Structure(持久化数据结构),也就是对于不需要改变的数据采用结构共享的方式。

  点击链接查看效果:

  https://vdn6.vzuu.com/SD/1cbd3a64-238b-11eb-b273-3ab99130e4ee.mp4?pkey=AAWnm1nWn8WVZRmFCwNiDTrJFRVmw_dbgixavz8kuqEgJpVyPgzjcFTWoTe9lYiFQkxRTa_Xrvf58rwCMA5BkKKt&c=avc.0.0&f=mp4&pu=078babd7&bu=078babd7&expiration=1661422409&v=ks6

  常用数据类型

  · List: 有序索引集,类似JS中的Array。

  · Map: 无序索引集,类似JS中的Object。

  · OrderedMap: 有序的Map,根据数据的set()进行排序。

  · Set: 没有重复值的集合。

  · OrderedSet: 有序的Set,根据数据的add进行排序。

  · Stack: 有序集合,支持使用unshift()和shift()添加和删除。

  · Record: 一个用于生成Record实例的类。类似于JavaScript的Object,但是只接收特定字符串为key,具有默认值。

  · Seq: 序列,但是可能不能由具体的数据结构支持。

  · Collection: 是构建所有数据结构的基类,不可以直接构建。

  正如你看到的,immutable.js的数据类型有很多,本文主要介绍比较常用的List和Map,对应于js中的数组和对象。

  js与immutable之间的转换

  可通过fromJS()和toJS()两个方式实现js和immuatble数据的转换,如:

  import Immutable from 'immutable';

  const goods = {name:'huawei mate30 pro',price:5998,brand:'huawei'}

  // js -> immutable data

  const imData = Immutable.fromJS(goods)

  // immutable data -> js

  imData.toJS()

  但fromJS()和toJS()会深度转换数据,随之带来的开销较大,尽可能避免使用,单层数据转换应直接使用Map()和List()进行转换。另外,还可以直接通过JSON.stringify()对immutable数据转换也json字符串。

  import {Map,List} from 'immutable';

  const initState = Map({

  breadcrumb:List([]),

  user:Map({}),

  manageMenuStatus:false

  })

  操作immutable数据

  获取immutable中的值:get(key)/getIn(keys)

  Map 和 List的通用方法,实现如下

  import {Map,List} from 'immutable';

  let state = Map({

  version:'2.0',

  user:Map({

  username:'laoxie',

  age:18,

  hobby:List(['代码','电影','唱歌'])

  }),

  })

  // 获取 version

  state.get('version');// 2.0

  // 获取username

  state.getIn(['user','username']);// laoxie

  // 获取hobby属性数据

  state.getIn(['user','hobby',1]) // 电影

  注意: 和传统的js不同,getIn()获取深层深套对象的值时不需要做每一层级的判断是否存在,如不存在则会返回undefined(JS中如果不判空会报错)

  · 添加immutable中的数据:set(key,val)/setIn(keys,val)

  · 删除属性:delete(key)/deleteIn(keys)

  · 更新属性:update(key,val=>newVal)/updateIn(keys,val=>newVal) 如开头所说的,Immutable Data为不可变数据,所有针对immutable的增删改都不会修改原数据,而是返回一个新的值,所以需要给变量重新赋值。

  import {Map,List} from 'immutable';

  let state = Map({

  version:'2.0',

  user:Map({

  id:'123',

  username:'laoxie',

  age:18,

  hobby:List(['代码','电影','唱歌'])

  }),

  })

  state.set('version','3.0');

  state.get('version');//state不被修改,所以还是返回2.0

  // 正确的修改方式:修改后重新赋值

  state = state.setIn(['user','age'],20);

  state.getIn(['user','age']);//20

  // update,delete操作同上

  · 判断是否存在某个属性:has(key)/hasIn(keys) 这应该也是实际开发中是比较常用的方法,通过判断属性是否存在来执行不同的操作,如可以判断user.id来判断用户是否登录

  if(state.hasIn(['user','id'])){

  // 用户已经登录

  }else{

  // 用户未登录

  }

  · 判断两个数据是否相等: is(imA,imB) 在JS中,不管是数据还是对象,通过==或===只能判断两个变量的引用地址是否为同一个对象,很难判断两个对象的键值是否相等,与JS不同,immutable是对两个对象的hashCode和valueOf进行比较的

  · 数据合并:merge()/mergeDeep() 还有一个比较常用的操作就是合并数据了,在JS我们一般使用Object.assign()来实现,但Object.assign()只能做浅合并,对层级较深的数据可以使用immutable中使用mergeDeep()来实现,两个方法都返回合并后的数据。

  const imA = Map({

  username:'马云',

  money:150000000000,

  info:{

  married:true,

  witticism:'我没见过钱,我对钱不感兴趣'

  }

  })

  const imB = Map({

  username:'laoxie',

  gender:'男',

  info:{

  married:false,

  age:18,

  }

  })

  const newImData = imA.merge(imB);

  console.log(newImData.toJS());

  //输出 :

  // {

  // username:'laoxie',

  // gender:'男',

  // money:150000000000,

  // info:{

  // married:false,

  // age:18,

  // }

  // }

  const newImData = imA.mergeDeep(imB);

  //输出 :

  // {

  // username:'laoxie',

  // gender:'男',

  // money:150000000000,

  // info:{

  // married:false,

  // age:18,

  // witticism:'我没见过钱,我对钱不感兴趣'

  // }

  // }

  当然Immutable的方法还有很多,本文本只涉及到一引起基本操作,如果想要了解跟多数据类型的操作,请自行查看官网。

tags:
声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。
10年以上业内强师集结,手把手带你蜕变精英
请您保持通讯畅通,专属学习老师24小时内将与您1V1沟通
免费领取
今日已有369人领取成功
刘同学 138****2860 刚刚成功领取
王同学 131****2015 刚刚成功领取
张同学 133****4652 刚刚成功领取
李同学 135****8607 刚刚成功领取
杨同学 132****5667 刚刚成功领取
岳同学 134****6652 刚刚成功领取
梁同学 157****2950 刚刚成功领取
刘同学 189****1015 刚刚成功领取
张同学 155****4678 刚刚成功领取
邹同学 139****2907 刚刚成功领取
董同学 138****2867 刚刚成功领取
周同学 136****3602 刚刚成功领取
相关推荐HOT
开班信息
北京校区
  • 北京校区
  • 大连校区
  • 广州校区
  • 成都校区
  • 杭州校区
  • 长沙校区
  • 合肥校区
  • 南京校区
  • 上海校区
  • 深圳校区
  • 武汉校区
  • 郑州校区
  • 西安校区
  • 青岛校区
  • 重庆校区
  • 太原校区
  • 沈阳校区
  • 南昌校区
  • 哈尔滨校区