浅谈Immutable.js

1 篇文章 0 订阅
1 篇文章 0 订阅

最近在学习Immutable.js,正好遇见公司的每周技术分享会,把自己的一些总结和学到的记录下来,分享给大家。

Immutable.js 简介

Immutable.js是由 Facebook 工程师( Lee Byron) 花费 3 年时间打造,与 React 同期出现,虽然没有被默认放到 React工具集里,但是它的价值还是非常大的。它内部实现了一套完整的持久化数据结构( Persistent Data Structure ),还有很多易用的数据类型(像 List、Map)。有非常全面的函数式操作方法( 像map、get、getIn、set、setIn、merge)。同时 API 也尽量与原生Js的 Object 和 Array 类似。

Immutable.js 原理

Immutable Data

  • Immutable Data 就是一旦创建,就不能再被更改的数据。对 Immutable 对象的任何修改、添加或删除操作都会返回一个新的 Immutable 对象。
  • Immutable 实现原理是持久化数据结构(Persistent Data Structure),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。
  • 为了避免深度拷贝(deep Copy)把所有节点都复制一遍带来的性能损耗,Immutable 使用了共享结构(Structural Sharing),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。

用一张图来说明
在这里插入图片描述

为什么要用Immutable?

这个就说来话长,直接上代码,从问题说起。(全文拿Object类型举例)

//  首先字符串声明和赋值,
let str1 = '123';
let str2 = str1;
str2 = '456';
console.log(str1); // '123'
console.log(str2);  // '456'
// 没有什么问题
// 对象的声明 和 赋值
let obj1 = { a : 1, b : 2 };
let obj2 = obj1; // 引用赋值
obj2.b = 5;
console.log(obj1.b); // 5
console.log(obj2.b); // 5
// 改变obj2中b的值,obj1中的b也会跟着变

这就是引用赋值在搞鬼,什么是引用赋值呢,拿上边的那个举例。obj1和obj2指向了js内存中的同一个对象,也就是指向同一个地址,共用一个源数据,所以,改变其中任何一个,其他引用的对象都会改变。

这就不得不说一下js的数据类型,引用类型的数据都是引用赋值。

  • 基本类型
    String、 Number、 Boolean、Undefined、 Null
  • 引用类型
    Object、 Array、 Function

js中也有解决引用赋值问题的方法

  • 浅拷贝
let obj1 = {
  a: 1,
  b: 2,
  c: {
    d: 3,
    e: 4
  }
};
let obj2 = Object.assign({}, obj1);
obj2.b = 5;
obj2.c.d = 6;
console.log(obj1.b);  // 2
console.log(obj2.b);  // 5
console.log(obj1.c.d);  // 6
console.log(obj2.c.d);  // 6

这段代码可以看出来,浅拷贝只能保证数据第一层的数据不会跟着变,嵌套的引用类型,还是会出现引用赋值的现象。

  • 深拷贝
let obj1 = {
  a: 1,
  b: 2,
  c: {
    d: 3,
    e: 4
  }
};
let obj2 = JSON.parse(JSON.stringify(obj1)); // 这里采用JSON的方法(先转化成字符串,再转换回去)进行深拷贝,当然还有其他方法。
obj2.b = 5;
obj2.c.d = 6;
console.log(obj1.b); // 2
console.log(obj2.b); // 5
console.log(obj1.c.d); // 3
console.log(obj2.c.d); // 6

这样就实现了对象的深拷贝。
完全可以解决问题。但是,下面介绍一下Immutable.js。对比一下。

Immutable 特点

  • 持久化数据结构(Persistent Data Structure)
  • 共享结构(Structural Sharing)
  • 速度快、用时短

有人做过这样一个实验

样本:1MB 的json文件(json对象),引入后深拷贝500份。
结果
JSON.parse(JSON.stringify())方法用时:2523.555176ms
immutable.fromJs()方法用时:1295.159912ms

可以看出来Immutable的速度明显比较快。

Immutable 最常用的且最重要的API

讲API之前,先说一下Immutable 的数据类型,毕竟Immutable主要是操作数据的。

Immutable 的数据类型

  • Map:无序索引集,类似 Js 中的 Object 。
  • List:有序索引集,类似 Js 中的 Array 。
  • OrderedMap:有序的Map,根据数据的set()进行排序。
  • Set:没有重复值的集合。
  • OrderedSet:有序的Set,根据数据的add进行排序。
  • Stack:有序集合,支持使用unshift()和shift()添加和删除。
  • Range
  • … (数据类型很多,我没有列完。因为我还没学到那儿,上面列出来的最常用的也就前两个)

Immutable 最常用的且最重要的API

  1. fromJS() 是最常用的将原生Js数据转换为Immutable数据的方法。
const obj = Immutable.fromJS({a: 1, b: 2, c: {d: 3, e: 4}});
  1. toJS() 是最常用的将原生 Immutable 数据转换为 Js 数据的方法。
const obj1 = Immutable.fromJS({a: 1, b: 2, c: {d: 3, e: 4}});
const obj2 = obj1.toJS();
  1. get() 和 getIn() 是Immutable 数据取值的方法。
const obj1 = Immutable.fromJS({a: 1, b: 2, c: {d: 3, e: 4}});
let b = obj1.get('b');
let d = obj1.getIn(['c', 'd']); // 嵌套值获取方式
  1. set() 、setIn() 和 merge() 是Immutable 数据修改数据的方法。返回修改后完整的数据,不会影响旧的数据。
const obj1 = Immutable.fromJS({a: 1, b: 2, c: {d: 3, e: 4}});
// 修改单个值
const obj2 = obj1.set('b', 5);  // ({a: 1, b: 5, c: {d: 3, e: 4}})
// 连写set修改同级多个值
const obj3 = obj1.set('a', 6).set('b', 5);  // ({a: 6, b: 5, c: {d: 3, e: 4}})
// merge修改多个值
const obj4 = obj1.merge({a: 6, b: 5}); // ({a: 6, b: 5, c: {d: 3, e: 4}})
// getIn修改嵌套的值
const obj5 = obj1.setIn(['c', 'd'], 6); // ({a: 1, b: 2, c: {d: 6, e: 4}})

下面来说一下Immutable的优点和缺点

  • 优点
    1、降低Mutable带来的复杂度
    原生Js的引用赋值虽然可以节省内存,但当应用复杂后,可变状态就会变成噩梦,通常一般的做法使用浅拷贝和深拷贝可以解决,但是这样造成了CPU和内存的消耗,Immutable可以很好的解决这些问题。
    2、节省内存空间
    前面提到的结构共享,Immutable.js使用这种方式会尽量的复用内存。
    3、随意穿梭
    因为每次数据都不一样,只要把这些数据放到一个数组中存起来,就可以作回退操作,很容易开发出撤销和回退的功能。
    4、拥抱函数式编程
    Immutable(持久化数据结构)本身就是函数式编程的概念,纯函数式编程比面向对象更适用于前端开发。因为只要输入一致,输出必然一致,这样开发的组件更易于调试和组装。
  • 缺点
    1、学习成本
    2、需要额外引入资源文件
    3、使用过程中容易与原生对象混淆

总结一下,什么时候该用Immutable?

首先得看你的项目中,深拷贝得需求量,如果整个项目也就那么三五个地方当需要用,那完全没必要用。用JSON的方法就可以了,或者自己用递归封装一个深度拷贝的方法。

上文中提到别人做的那个实验,Immutable耗时短,得看前提,他的前提是1M得数据,拷贝500份,平常项目中得数据一般都很小,如果深拷贝用到的少,完全可以不用Immutable。如果用到的多,可以考虑用。比如react项目中,不允许直接改变state的值,这时用Immutable就很合适。

还有就是特殊功能的项目,比如说上面提到的优点第3条,项目需要做回退操作或撤销操作的功能,用Immutable实现很方便。

以上全是本人自己学习Immutablede时的一些个人看法,如有不对的地方请指正。本文只写了Immutable中最基本最常用的功能,还有很多没写,以后有机会再深入写一下。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值