Immutable
Immutable Data 就是一旦创建,就不能再被更改的数据。对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。Immutable 实现的原理是 Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了Structural Sharing(结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。
官网地址:https://github.com/immutable-js/immutable-js
深拷贝与浅拷贝的关系
(1) var arr = { } ; arr2 = arr ;
(2) Object.assign() 只是一级属性复制,比浅拷贝多拷贝了一层而已。
(3) const obj1 = JSON.parse(JSON.stringify(obj)); 数组,对象都好用的方法(缺点: 不能有undefined)
Immutable性能优化方式
Immutable 实现的原理是 Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了 Structural Sharing(结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。
Immutable常用数据类型
1.Map
1 2 3 4
| const { Map } = require('immutable'); const map1 = Map({ a: 1, b: 2, c: 3 }); const map2 = map1.set('b', 50); map1.get('b') + " vs. " + map2.get('b');
|
简单应用场景:
1 2 3 4 5 6 7 8 9
| import {Map} from 'immutable' let a = Map({ select:'users', filter:Map({name:'sola'}) }) let b = a.set('select','people')
a === b a.get('filter') === b.get('filter')
|
如果上述select属性给一个组件用,因此值改变了,shouldComponentUpdate应该返回true,而filter属性给另一个组件使用,通过判断并无变化,shouldComponentUpdate应该返回false。此组件就避免了重复进行diff对比
2.List
1 2 3 4 5 6 7 8 9 10 11
| const { List } = require('immutable'); const list1 = List([ 1, 2 ]); const list2 = list1.push(3, 4, 5); const list3 = list2.unshift(0); const list4 = list1.concat(list2, list3); assert.equal(list1.size, 2); assert.equal(list2.size, 5); assert.equal(list3.size, 6); assert.equal(list4.size, 13); assert.equal(list4.get(0), 1);
|
3.merge,concat
1 2 3 4 5 6 7 8 9 10 11
| const { Map, List } = require('immutable'); const map1 = Map({ a: 1, b: 2, c: 3, d: 4 }); const map2 = Map({ c: 10, a: 20, t: 30 }); const obj = { d: 100, o: 200, g: 300 }; const map3 = map1.merge(map2, obj);
const list1 = List([ 1, 2, 3 ]); const list2 = List([ 4, 5, 6 ]); const array = [ 7, 8, 9 ]; const list3 = list1.concat(list2, array);
|
4.toJS
将immutable转成普通JS对象
1 2 3 4 5 6
| const { Map, List } = require('immutable'); const deep = Map({ a: 1, b: 2, c: List([ 3, 4, 5 ]) }); console.log(deep.toObject()); console.log(deep.toArray()); console.log(deep.toJS()); JSON.stringify(deep);
|
5.fromJS
将普通JS对象转为immutable对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const { fromJS } = require('immutable'); const nested = fromJS({ a: { b: { c: [ 3, 4, 5 ] } } });
const nested2 = nested.mergeDeep({ a: { b: { d: 6 } } });
console.log(nested2.getIn([ 'a', 'b', 'd' ]));
const nested3 = nested2.setIn([ 'a', 'b', 'd' ], "kerwin");
const nested3 = nested2.updateIn([ 'a', 'b', 'd' ], value => value + 1); console.log(nested3);
const nested4 = nested3.updateIn([ 'a', 'b', 'c' ], list => list.push(6));
|
redux Immutable应用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| const initialState = fromJS({category: "", material: ""}) const reducer = (prevstate = initialState, action = {}) => { let {type, payload} = action switch (type) { case GET_HOME: var newstate = prevstate.set("category", fromJS(payload.category)) var newstate2 = newstate.set("material", fromJS(payload.material)) return newstate2; default: return prevstate } }
const mapStateToProps = (state) => { return { category: state.homeReducer.getIn(["category"]) || Map({}), material: state.homeReducer.getIn(["material"]) || Map({}) } } this.props.category.get("相关属性") this.props.category.toJS()
|
Immutable也存在一定的缺点: