<commit_before>---
layout:     post
title:      "2017-09-07-immutable"
date:       "2017-09-07 "
author:     "guozhaodong"
---

### 为什么会出现`immutable`

在`javascript`中对象都是引用类型的，新的对象对象引用了原始对象，改变新对象原始对象也会改变。

``` js
let foo = {a:1}
let bar = foo;
bar.a=2;
console.log('bar.a:'+bar.a);
console.log('foo.a:'+foo.a);
```

为了解决这个问题我们一般采用的是<strong>浅拷贝</strong>(`shadowCopy`)或<strong>深拷贝</strong>(`deepCopy`)来避免这种问题，但是这种做`cpu`和内存的浪费。

这时`Immutable`的出现很好地解决了这个问题，既能对数据进行深拷贝，同时也不会很耗性能。


### `immutable`是什么？

持久化数据或不可变数据，可以理解为另一种数据结构的库。通过`Immutable`创建出来的数据，一旦被创建就不能再被更改；对`Immutable`对象的任何添加、修改、删除操作都会返回一个新的`Immutable`对象。

``` js
import {Map} from 'immutable';

//Map
const map1 = Map({a:1});
const map2 = map1.set('a',2);
console.log('map1.a:'+map1.get('a'))
console.log('map2.a:'+map2.get('a'))
```

### `immutable`的实现原理

`Immutable`的实现原理是`Persistent Data Structure`（持久化数据结构），即使用旧数据创建新数据时，会保证旧数据可用且不变，同时为了避免`deepCopy`把所有节点都复制一遍带来的性能损耗，`Immutable`使用了`Structural Sharing`（结构共享），即如果对象数中一个节点发生变化，只修改这个节点和受它影响的父节点，其它节点则进行共享，如下图：

![image](../img/immutable/TB1zzi_KXXXXXctXFXXbrb8OVXX-613-575.gif)


### `immutable`的`api`介绍

`immutable`内部实现了一整套的持久化数据结构，

- 数据类型，比如`Collection`、`List`、`Map`、`OrderedMap`、`Set`、`OrderedSet`、`Stack`、`Record`、`Seq`。

- 全局方法(挂在`Immutable`对象下面的)，`fromJS()`、`is()`、`hash()`、`isImmutable()`、`isCollection`、`isKeyed()`、`isIndexed()`、`isAssociative()`、`isOrdered()`、`isValueObject()`、`Range()`、`Repeat()`等。

- 静态方法（挂在`Immutable Data`上的），如`List.isList()`、`List.of()`、`Map.isMap()`等

- 实例方法（挂在`Immutable Data`的实例上的），如`map()`、`filter()`、`groupBy()`、`reduce()`、`find()`等等，方法非常多具体查看官方`api`。

比较重要且用的比较多的数据类型：

- `List`：有序可重复的列表，对应`Array`。
- `Map`：键值对集合，对应`Object`，`ES6`也有专门的`Map`对象。
- `Set`：无须且不可重复的列表，`ES6`中也有专门的`Set`对象。

简单介绍几个常用的方法

`fromJS()`：接受原生`js`类型数据，返回`immutable`类型数据。

``` js
import Immutable from 'immutable';
console.log(Immutable.fromJS([1,{a:2},{b:[3,4,5]}]))
```

`is()`：接受两个`immutable`数据,返回一个布尔值，表示这两个数据是否相等

``` js
import Immutable from 'immutable';
const obj1 = Map({a:1,b:2});
const obj2 = Map({a:1,b:2});
console.log(obj1==obj2);
console.log(Immutable.is(obj1,obj2));
```

`hash()`：接受一个`immutable`数据,返回一个31位的整数，这个值就是每一个`immutable`数据的唯一表示，用来判断两个数据是否相等的。

``` js
import Immutable from 'immutable';
const obj1 = Map({a:1,b:2});
const obj2 = Map({a:1,b:2});
console.log('obj1.hash:'+Immutable.hash(obj1));
console.log('obj2.hash:'+Immutable.hash(obj2));
```

`List()`：接受原生`js`的`Array`，返回`immutable`的`List`

``` js
import Immutable from 'immutable';
console.log(Immutable.List([1,2,[3,4]]))
```


`Map()`：接受原生`js`的`Object`，返回`immutable`的`Map`

``` js
import Immutable from 'immutable';
console.log(Immutable.Map({a:1,b:{c:2}}))
```

`toJS()`：接受`immutable`类型数据，返回原生`js`类型数据，与`fromJS()`相反。

``` js
import Immutable from 'immutable';
const data1 = Immutable.fromJS([1,2,3])
console.log(data1.toJS())
```

`set()`：接受`immutable`类型数据，返回一个新的`immutable`数据,如果值存在则替换。

``` js
import Immutable from 'immutable';
const list = Immutable.List([1,2,3])
console.log(list.set(3,4))

const map = Immutable.Map({a:1,b:2,c:3})
console.log(map.set('d',4))
```


用一张图来罗列下`immutable`数据之前的继承关系

![image](../img/immutable/TM20170906144039.png)


### 在`React`中使用`immutable`

#### 为什么要在`React`中使用？<commit_msg>modify immutable<commit_after>---
layout:     post
title:      "2017-09-07-immutable"
date:       "2017-09-07 "
author:     "guozhaodong"
---

### 为什么会出现`immutable`

在`javascript`中对象都是引用类型的，新的对象对象引用了原始对象，改变新对象原始对象也会改变。

``` js
let foo = {a:1}
let bar = foo;
bar.a=2;
console.log('bar.a:'+bar.a);
console.log('foo.a:'+foo.a);
```

为了解决这个问题我们一般采用的是<strong>浅拷贝</strong>(`shadowCopy`)或<strong>深拷贝</strong>(`deepCopy`)来避免这种问题，但是这种做`cpu`和内存的浪费。

这时`Immutable`的出现很好地解决了这个问题，既能对数据进行深拷贝，同时也不会很耗性能。


### `immutable`是什么？

持久化数据或不可变数据，可以理解为另一种数据结构的库。通过`Immutable`创建出来的数据，一旦被创建就不能再被更改；对`Immutable`对象的任何添加、修改、删除操作都会返回一个新的`Immutable`对象。

``` js
import {Map} from 'immutable';

//Map
const map1 = Map({a:1});
const map2 = map1.set('a',2);
console.log('map1.a:'+map1.get('a'))
console.log('map2.a:'+map2.get('a'))
```

### `immutable`的实现原理

`Immutable`的实现原理是`Persistent Data Structure`（持久化数据结构），即使用旧数据创建新数据时，会保证旧数据可用且不变，同时为了避免`deepCopy`把所有节点都复制一遍带来的性能损耗，`Immutable`使用了`Structural Sharing`（结构共享），即如果对象数中一个节点发生变化，只修改这个节点和受它影响的父节点，其它节点则进行共享，如下图：

![image](../img/immutable/TB1zzi_KXXXXXctXFXXbrb8OVXX-613-575.gif)


### `immutable`的`api`介绍

`immutable`内部实现了一整套的持久化数据结构，

- 数据类型，比如`Collection`、`List`、`Map`、`OrderedMap`、`Set`、`OrderedSet`、`Stack`、`Record`、`Seq`。

- 全局方法(挂在`Immutable`对象下面的)，`fromJS()`、`is()`、`hash()`、`isImmutable()`、`isCollection`、`isKeyed()`、`isIndexed()`、`isAssociative()`、`isOrdered()`、`isValueObject()`、`Range()`、`Repeat()`等。

- 静态方法（挂在`Immutable Data`上的），如`List.isList()`、`List.of()`、`Map.isMap()`等

- 实例方法（挂在`Immutable Data`的实例上的），如`map()`、`filter()`、`groupBy()`、`reduce()`、`find()`等等，方法非常多具体查看官方`api`。

比较重要且用的比较多的数据类型：

- `List`：有序可重复的列表，对应`Array`。
- `Map`：键值对集合，对应`Object`，`ES6`也有专门的`Map`对象。
- `Set`：无须且不可重复的列表，`ES6`中也有专门的`Set`对象。

简单介绍几个常用的方法

`fromJS()`：接受原生`js`类型数据，返回`immutable`类型数据。

``` js
import Immutable from 'immutable';
console.log(Immutable.fromJS([1,{a:2},{b:[3,4,5]}]))
```

`is()`：接受两个`immutable`数据,返回一个布尔值，表示这两个数据是否相等

``` js
import Immutable from 'immutable';
const obj1 = Map({a:1,b:2});
const obj2 = Map({a:1,b:2});
console.log(obj1==obj2);
console.log(Immutable.is(obj1,obj2));
```

`hash()`：接受一个`immutable`数据,返回一个31位的整数，这个值就是每一个`immutable`数据的唯一表示，用来判断两个数据是否相等的。

``` js
import Immutable from 'immutable';
const obj1 = Map({a:1,b:2});
const obj2 = Map({a:1,b:2});
console.log('obj1.hash:'+Immutable.hash(obj1));
console.log('obj2.hash:'+Immutable.hash(obj2));
```

`List()`：接受原生`js`的`Array`，返回`immutable`的`List`

``` js
import Immutable from 'immutable';
console.log(Immutable.List([1,2,[3,4]]))
```

`Map()`：接受原生`js`的`Object`，返回`immutable`的`Map`

``` js
import Immutable from 'immutable';
console.log(Immutable.Map({a:1,b:{c:2}}))
```

`toJS()`：接受`immutable`类型数据，返回原生`js`类型数据，与`fromJS()`相反。

``` js
import Immutable from 'immutable';
const data1 = Immutable.fromJS([1,2,3])
console.log(data1.toJS())
```

`set()`：接受`immutable`类型数据，返回一个新的`immutable`数据,如果值存在则替换。

``` js
import Immutable from 'immutable';
const list = Immutable.List([1,2,3])
console.log(list.set(3,4))

const map = Immutable.Map({a:1,b:2,c:3})
console.log(map.set('d',4))
```


用一张图来罗列下`immutable`数据之前的继承关系

![image](/img/immutable/TM20170906144039.png)


### 在`React`中使用`immutable`

#### 为什么要在`React`中使用？
{'fraction_non_alphanumeric': 0.2344482650828384, 'fraction_numerical': 0.030634573304157548, 'mean_word_length': 9.04552590266876, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5692240', 'n_tokens_mistral': 3653, 'n_tokens_neox': 3761, 'n_words': 270}