[d24f17c] | 1 | Immutable collections for JavaScript
|
---|
| 2 | ====================================
|
---|
| 3 |
|
---|
| 4 | [](https://travis-ci.org/facebook/immutable-js)
|
---|
| 5 |
|
---|
| 6 | [Immutable][] data cannot be changed once created, leading to much simpler
|
---|
| 7 | application development, no defensive copying, and enabling advanced memoization
|
---|
| 8 | and change detection techniques with simple logic. [Persistent][] data presents
|
---|
| 9 | a mutative API which does not update the data in-place, but instead always
|
---|
| 10 | yields new updated data.
|
---|
| 11 |
|
---|
| 12 | Immutable.js provides many Persistent Immutable data structures including:
|
---|
| 13 | `List`, `Stack`, `Map`, `OrderedMap`, `Set`, `OrderedSet` and `Record`.
|
---|
| 14 |
|
---|
| 15 | These data structures are highly efficient on modern JavaScript VMs by using
|
---|
| 16 | structural sharing via [hash maps tries][] and [vector tries][] as popularized
|
---|
| 17 | by Clojure and Scala, minimizing the need to copy or cache data.
|
---|
| 18 |
|
---|
| 19 | `Immutable` also provides a lazy `Seq`, allowing efficient
|
---|
| 20 | chaining of collection methods like `map` and `filter` without creating
|
---|
| 21 | intermediate representations. Create some `Seq` with `Range` and `Repeat`.
|
---|
| 22 |
|
---|
| 23 | Want to hear more? Watch the presentation about Immutable.js:
|
---|
| 24 |
|
---|
| 25 | <a href="https://youtu.be/I7IdS-PbEgI" target="_blank" alt="Immutable Data and React"><img src="https://img.youtube.com/vi/I7IdS-PbEgI/0.jpg" /></a>
|
---|
| 26 |
|
---|
| 27 | [Persistent]: http://en.wikipedia.org/wiki/Persistent_data_structure
|
---|
| 28 | [Immutable]: http://en.wikipedia.org/wiki/Immutable_object
|
---|
| 29 | [hash maps tries]: http://en.wikipedia.org/wiki/Hash_array_mapped_trie
|
---|
| 30 | [vector tries]: http://hypirion.com/musings/understanding-persistent-vector-pt-1
|
---|
| 31 |
|
---|
| 32 |
|
---|
| 33 | Getting started
|
---|
| 34 | ---------------
|
---|
| 35 |
|
---|
| 36 | Install `immutable` using npm.
|
---|
| 37 |
|
---|
| 38 | ```shell
|
---|
| 39 | npm install immutable
|
---|
| 40 | ```
|
---|
| 41 |
|
---|
| 42 | Then require it into any module.
|
---|
| 43 |
|
---|
| 44 | ```javascript
|
---|
| 45 | var Immutable = require('immutable');
|
---|
| 46 | var map1 = Immutable.Map({a:1, b:2, c:3});
|
---|
| 47 | var map2 = map1.set('b', 50);
|
---|
| 48 | map1.get('b'); // 2
|
---|
| 49 | map2.get('b'); // 50
|
---|
| 50 | ```
|
---|
| 51 |
|
---|
| 52 | ### Browser
|
---|
| 53 |
|
---|
| 54 | To use `immutable` from a browser, download [dist/immutable.min.js](https://github.com/facebook/immutable-js/blob/master/dist/immutable.min.js)
|
---|
| 55 | or use a CDN such as [CDNJS](https://cdnjs.com/libraries/immutable)
|
---|
| 56 | or [jsDelivr](http://www.jsdelivr.com/#!immutable.js).
|
---|
| 57 |
|
---|
| 58 | Then, add it as a script tag to your page:
|
---|
| 59 |
|
---|
| 60 | ```html
|
---|
| 61 | <script src="immutable.min.js"></script>
|
---|
| 62 | <script>
|
---|
| 63 | var map1 = Immutable.Map({a:1, b:2, c:3});
|
---|
| 64 | var map2 = map1.set('b', 50);
|
---|
| 65 | map1.get('b'); // 2
|
---|
| 66 | map2.get('b'); // 50
|
---|
| 67 | </script>
|
---|
| 68 | ```
|
---|
| 69 |
|
---|
| 70 | Or use an AMD loader (such as [RequireJS](http://requirejs.org/)):
|
---|
| 71 |
|
---|
| 72 | ```javascript
|
---|
| 73 | require(['./immutable.min.js'], function (Immutable) {
|
---|
| 74 | var map1 = Immutable.Map({a:1, b:2, c:3});
|
---|
| 75 | var map2 = map1.set('b', 50);
|
---|
| 76 | map1.get('b'); // 2
|
---|
| 77 | map2.get('b'); // 50
|
---|
| 78 | });
|
---|
| 79 | ```
|
---|
| 80 |
|
---|
| 81 | If you're using [browserify](http://browserify.org/), the `immutable` npm module
|
---|
| 82 | also works from the browser.
|
---|
| 83 |
|
---|
| 84 | ### TypeScript
|
---|
| 85 |
|
---|
| 86 | Use these Immutable collections and sequences as you would use native
|
---|
| 87 | collections in your [TypeScript](http://typescriptlang.org) programs while still taking
|
---|
| 88 | advantage of type generics, error detection, and auto-complete in your IDE.
|
---|
| 89 |
|
---|
| 90 | Just add a reference with a relative path to the type declarations at the top
|
---|
| 91 | of your file.
|
---|
| 92 |
|
---|
| 93 | ```javascript
|
---|
| 94 | ///<reference path='./node_modules/immutable/dist/immutable.d.ts'/>
|
---|
| 95 | import Immutable = require('immutable');
|
---|
| 96 | var map1: Immutable.Map<string, number>;
|
---|
| 97 | map1 = Immutable.Map({a:1, b:2, c:3});
|
---|
| 98 | var map2 = map1.set('b', 50);
|
---|
| 99 | map1.get('b'); // 2
|
---|
| 100 | map2.get('b'); // 50
|
---|
| 101 | ```
|
---|
| 102 |
|
---|
| 103 |
|
---|
| 104 | The case for Immutability
|
---|
| 105 | -------------------------
|
---|
| 106 |
|
---|
| 107 | Much of what makes application development difficult is tracking mutation and
|
---|
| 108 | maintaining state. Developing with immutable data encourages you to think
|
---|
| 109 | differently about how data flows through your application.
|
---|
| 110 |
|
---|
| 111 | Subscribing to data events throughout your application creates a huge overhead of
|
---|
| 112 | book-keeping which can hurt performance, sometimes dramatically, and creates
|
---|
| 113 | opportunities for areas of your application to get out of sync with each other
|
---|
| 114 | due to easy to make programmer error. Since immutable data never changes,
|
---|
| 115 | subscribing to changes throughout the model is a dead-end and new data can only
|
---|
| 116 | ever be passed from above.
|
---|
| 117 |
|
---|
| 118 | This model of data flow aligns well with the architecture of [React][]
|
---|
| 119 | and especially well with an application designed using the ideas of [Flux][].
|
---|
| 120 |
|
---|
| 121 | When data is passed from above rather than being subscribed to, and you're only
|
---|
| 122 | interested in doing work when something has changed, you can use equality.
|
---|
| 123 |
|
---|
| 124 | Immutable collections should be treated as *values* rather than *objects*. While
|
---|
| 125 | objects represents some thing which could change over time, a value represents
|
---|
| 126 | the state of that thing at a particular instance of time. This principle is most
|
---|
| 127 | important to understanding the appropriate use of immutable data. In order to
|
---|
| 128 | treat Immutable.js collections as values, it's important to use the
|
---|
| 129 | `Immutable.is()` function or `.equals()` method to determine value equality
|
---|
| 130 | instead of the `===` operator which determines object reference identity.
|
---|
| 131 |
|
---|
| 132 | ```javascript
|
---|
| 133 | var map1 = Immutable.Map({a:1, b:2, c:3});
|
---|
| 134 | var map2 = map1.set('b', 2);
|
---|
| 135 | assert(map1.equals(map2) === true);
|
---|
| 136 | var map3 = map1.set('b', 50);
|
---|
| 137 | assert(map1.equals(map3) === false);
|
---|
| 138 | ```
|
---|
| 139 |
|
---|
| 140 | Note: As a performance optimization `Immutable` attempts to return the existing
|
---|
| 141 | collection when an operation would result in an identical collection, allowing
|
---|
| 142 | for using `===` reference equality to determine if something definitely has not
|
---|
| 143 | changed. This can be extremely useful when used within memoization function
|
---|
| 144 | which would prefer to re-run the function if a deeper equality check could
|
---|
| 145 | potentially be more costly. The `===` equality check is also used internally by
|
---|
| 146 | `Immutable.is` and `.equals()` as a performance optimization.
|
---|
| 147 |
|
---|
| 148 | If an object is immutable, it can be "copied" simply by making another reference
|
---|
| 149 | to it instead of copying the entire object. Because a reference is much smaller
|
---|
| 150 | than the object itself, this results in memory savings and a potential boost in
|
---|
| 151 | execution speed for programs which rely on copies (such as an undo-stack).
|
---|
| 152 |
|
---|
| 153 | ```javascript
|
---|
| 154 | var map1 = Immutable.Map({a:1, b:2, c:3});
|
---|
| 155 | var clone = map1;
|
---|
| 156 | ```
|
---|
| 157 |
|
---|
| 158 | [React]: http://facebook.github.io/react/
|
---|
| 159 | [Flux]: http://facebook.github.io/flux/docs/overview.html
|
---|
| 160 |
|
---|
| 161 |
|
---|
| 162 | JavaScript-first API
|
---|
| 163 | --------------------
|
---|
| 164 |
|
---|
| 165 | While `immutable` is inspired by Clojure, Scala, Haskell and other functional
|
---|
| 166 | programming environments, it's designed to bring these powerful concepts to
|
---|
| 167 | JavaScript, and therefore has an Object-Oriented API that closely mirrors that
|
---|
| 168 | of [ES6][] [Array][], [Map][], and [Set][].
|
---|
| 169 |
|
---|
| 170 | [ES6]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla
|
---|
| 171 | [Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
|
---|
| 172 | [Map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
|
---|
| 173 | [Set]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
|
---|
| 174 |
|
---|
| 175 | The difference for the immutable collections is that methods which would mutate
|
---|
| 176 | the collection, like `push`, `set`, `unshift` or `splice` instead return a new
|
---|
| 177 | immutable collection. Methods which return new arrays like `slice` or `concat`
|
---|
| 178 | instead return new immutable collections.
|
---|
| 179 |
|
---|
| 180 | ```javascript
|
---|
| 181 | var list1 = Immutable.List.of(1, 2);
|
---|
| 182 | var list2 = list1.push(3, 4, 5);
|
---|
| 183 | var list3 = list2.unshift(0);
|
---|
| 184 | var list4 = list1.concat(list2, list3);
|
---|
| 185 | assert(list1.size === 2);
|
---|
| 186 | assert(list2.size === 5);
|
---|
| 187 | assert(list3.size === 6);
|
---|
| 188 | assert(list4.size === 13);
|
---|
| 189 | assert(list4.get(0) === 1);
|
---|
| 190 | ```
|
---|
| 191 |
|
---|
| 192 | Almost all of the methods on [Array][] will be found in similar form on
|
---|
| 193 | `Immutable.List`, those of [Map][] found on `Immutable.Map`, and those of [Set][]
|
---|
| 194 | found on `Immutable.Set`, including collection operations like `forEach()`
|
---|
| 195 | and `map()`.
|
---|
| 196 |
|
---|
| 197 | ```javascript
|
---|
| 198 | var alpha = Immutable.Map({a:1, b:2, c:3, d:4});
|
---|
| 199 | alpha.map((v, k) => k.toUpperCase()).join();
|
---|
| 200 | // 'A,B,C,D'
|
---|
| 201 | ```
|
---|
| 202 |
|
---|
| 203 | ### Accepts raw JavaScript objects.
|
---|
| 204 |
|
---|
| 205 | Designed to inter-operate with your existing JavaScript, `immutable`
|
---|
| 206 | accepts plain JavaScript Arrays and Objects anywhere a method expects an
|
---|
| 207 | `Iterable` with no performance penalty.
|
---|
| 208 |
|
---|
| 209 | ```javascript
|
---|
| 210 | var map1 = Immutable.Map({a:1, b:2, c:3, d:4});
|
---|
| 211 | var map2 = Immutable.Map({c:10, a:20, t:30});
|
---|
| 212 | var obj = {d:100, o:200, g:300};
|
---|
| 213 | var map3 = map1.merge(map2, obj);
|
---|
| 214 | // Map { a: 20, b: 2, c: 10, d: 100, t: 30, o: 200, g: 300 }
|
---|
| 215 | ```
|
---|
| 216 |
|
---|
| 217 | This is possible because `immutable` can treat any JavaScript Array or Object
|
---|
| 218 | as an Iterable. You can take advantage of this in order to get sophisticated
|
---|
| 219 | collection methods on JavaScript Objects, which otherwise have a very sparse
|
---|
| 220 | native API. Because Seq evaluates lazily and does not cache intermediate
|
---|
| 221 | results, these operations can be extremely efficient.
|
---|
| 222 |
|
---|
| 223 | ```javascript
|
---|
| 224 | var myObject = {a:1,b:2,c:3};
|
---|
| 225 | Immutable.Seq(myObject).map(x => x * x).toObject();
|
---|
| 226 | // { a: 1, b: 4, c: 9 }
|
---|
| 227 | ```
|
---|
| 228 |
|
---|
| 229 | Keep in mind, when using JS objects to construct Immutable Maps, that
|
---|
| 230 | JavaScript Object properties are always strings, even if written in a quote-less
|
---|
| 231 | shorthand, while Immutable Maps accept keys of any type.
|
---|
| 232 |
|
---|
| 233 | ```js
|
---|
| 234 | var obj = { 1: "one" };
|
---|
| 235 | Object.keys(obj); // [ "1" ]
|
---|
| 236 | obj["1"]; // "one"
|
---|
| 237 | obj[1]; // "one"
|
---|
| 238 |
|
---|
| 239 | var map = Immutable.fromJS(obj);
|
---|
| 240 | map.get("1"); // "one"
|
---|
| 241 | map.get(1); // undefined
|
---|
| 242 | ```
|
---|
| 243 |
|
---|
| 244 | Property access for JavaScript Objects first converts the key to a string, but
|
---|
| 245 | since Immutable Map keys can be of any type the argument to `get()` is
|
---|
| 246 | not altered.
|
---|
| 247 |
|
---|
| 248 |
|
---|
| 249 | ### Converts back to raw JavaScript objects.
|
---|
| 250 |
|
---|
| 251 | All `immutable` Iterables can be converted to plain JavaScript Arrays and
|
---|
| 252 | Objects shallowly with `toArray()` and `toObject()` or deeply with `toJS()`.
|
---|
| 253 | All Immutable Iterables also implement `toJSON()` allowing them to be passed to
|
---|
| 254 | `JSON.stringify` directly.
|
---|
| 255 |
|
---|
| 256 | ```javascript
|
---|
| 257 | var deep = Immutable.Map({ a: 1, b: 2, c: Immutable.List.of(3, 4, 5) });
|
---|
| 258 | deep.toObject() // { a: 1, b: 2, c: List [ 3, 4, 5 ] }
|
---|
| 259 | deep.toArray() // [ 1, 2, List [ 3, 4, 5 ] ]
|
---|
| 260 | deep.toJS() // { a: 1, b: 2, c: [ 3, 4, 5 ] }
|
---|
| 261 | JSON.stringify(deep) // '{"a":1,"b":2,"c":[3,4,5]}'
|
---|
| 262 | ```
|
---|
| 263 |
|
---|
| 264 | ### Embraces ES6
|
---|
| 265 |
|
---|
| 266 | `Immutable` takes advantage of features added to JavaScript in [ES6][],
|
---|
| 267 | the latest standard version of ECMAScript (JavaScript), including [Iterators][],
|
---|
| 268 | [Arrow Functions][], [Classes][], and [Modules][]. It's also inspired by the
|
---|
| 269 | [Map][] and [Set][] collections added to ES6. The library is "transpiled" to ES3
|
---|
| 270 | in order to support all modern browsers.
|
---|
| 271 |
|
---|
| 272 | All examples are presented in ES6. To run in all browsers, they need to be
|
---|
| 273 | translated to ES3.
|
---|
| 274 |
|
---|
| 275 | ```js
|
---|
| 276 | // ES6
|
---|
| 277 | foo.map(x => x * x);
|
---|
| 278 | // ES3
|
---|
| 279 | foo.map(function (x) { return x * x; });
|
---|
| 280 | ```
|
---|
| 281 |
|
---|
| 282 | [Iterators]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/The_Iterator_protocol
|
---|
| 283 | [Arrow Functions]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
|
---|
| 284 | [Classes]: http://wiki.ecmascript.org/doku.php?id=strawman:maximally_minimal_classes
|
---|
| 285 | [Modules]: http://www.2ality.com/2014/09/es6-modules-final.html
|
---|
| 286 |
|
---|
| 287 |
|
---|
| 288 | Nested Structures
|
---|
| 289 | -----------------
|
---|
| 290 |
|
---|
| 291 | The collections in `immutable` are intended to be nested, allowing for deep
|
---|
| 292 | trees of data, similar to JSON.
|
---|
| 293 |
|
---|
| 294 | ```javascript
|
---|
| 295 | var nested = Immutable.fromJS({a:{b:{c:[3,4,5]}}});
|
---|
| 296 | // Map { a: Map { b: Map { c: List [ 3, 4, 5 ] } } }
|
---|
| 297 | ```
|
---|
| 298 |
|
---|
| 299 | A few power-tools allow for reading and operating on nested data. The
|
---|
| 300 | most useful are `mergeDeep`, `getIn`, `setIn`, and `updateIn`, found on `List`,
|
---|
| 301 | `Map` and `OrderedMap`.
|
---|
| 302 |
|
---|
| 303 | ```javascript
|
---|
| 304 | var nested2 = nested.mergeDeep({a:{b:{d:6}}});
|
---|
| 305 | // Map { a: Map { b: Map { c: List [ 3, 4, 5 ], d: 6 } } }
|
---|
| 306 | ```
|
---|
| 307 |
|
---|
| 308 | ```javascript
|
---|
| 309 | nested2.getIn(['a', 'b', 'd']); // 6
|
---|
| 310 |
|
---|
| 311 | var nested3 = nested2.updateIn(['a', 'b', 'd'], value => value + 1);
|
---|
| 312 | // Map { a: Map { b: Map { c: List [ 3, 4, 5 ], d: 7 } } }
|
---|
| 313 |
|
---|
| 314 | var nested4 = nested3.updateIn(['a', 'b', 'c'], list => list.push(6));
|
---|
| 315 | // Map { a: Map { b: Map { c: List [ 3, 4, 5, 6 ], d: 7 } } }
|
---|
| 316 | ```
|
---|
| 317 |
|
---|
| 318 |
|
---|
| 319 | Lazy Seq
|
---|
| 320 | --------
|
---|
| 321 |
|
---|
| 322 | `Seq` describes a lazy operation, allowing them to efficiently chain
|
---|
| 323 | use of all the Iterable methods (such as `map` and `filter`).
|
---|
| 324 |
|
---|
| 325 | **Seq is immutable** — Once a Seq is created, it cannot be
|
---|
| 326 | changed, appended to, rearranged or otherwise modified. Instead, any mutative
|
---|
| 327 | method called on a Seq will return a new Seq.
|
---|
| 328 |
|
---|
| 329 | **Seq is lazy** — Seq does as little work as necessary to respond to any
|
---|
| 330 | method call.
|
---|
| 331 |
|
---|
| 332 | For example, the following does not perform any work, because the resulting
|
---|
| 333 | Seq is never used:
|
---|
| 334 |
|
---|
| 335 | var oddSquares = Immutable.Seq.of(1,2,3,4,5,6,7,8)
|
---|
| 336 | .filter(x => x % 2).map(x => x * x);
|
---|
| 337 |
|
---|
| 338 | Once the Seq is used, it performs only the work necessary. In this
|
---|
| 339 | example, no intermediate arrays are ever created, filter is called three times,
|
---|
| 340 | and map is only called twice:
|
---|
| 341 |
|
---|
| 342 | console.log(oddSquares.get(1)); // 9
|
---|
| 343 |
|
---|
| 344 | Any collection can be converted to a lazy Seq with `.toSeq()`.
|
---|
| 345 |
|
---|
| 346 | var seq = Immutable.Map({a:1, b:1, c:1}).toSeq();
|
---|
| 347 |
|
---|
| 348 | Seq allow for the efficient chaining of sequence operations, especially when
|
---|
| 349 | converting to a different concrete type (such as to a JS object):
|
---|
| 350 |
|
---|
| 351 | seq.flip().map(key => key.toUpperCase()).flip().toObject();
|
---|
| 352 | // Map { A: 1, B: 1, C: 1 }
|
---|
| 353 |
|
---|
| 354 | As well as expressing logic that would otherwise seem memory-limited:
|
---|
| 355 |
|
---|
| 356 | Immutable.Range(1, Infinity)
|
---|
| 357 | .skip(1000)
|
---|
| 358 | .map(n => -n)
|
---|
| 359 | .filter(n => n % 2 === 0)
|
---|
| 360 | .take(2)
|
---|
| 361 | .reduce((r, n) => r * n, 1);
|
---|
| 362 | // 1006008
|
---|
| 363 |
|
---|
| 364 | Note: An iterable is always iterated in the same order, however that order may
|
---|
| 365 | not always be well defined, as is the case for the `Map`.
|
---|
| 366 |
|
---|
| 367 |
|
---|
| 368 | Equality treats Collections as Data
|
---|
| 369 | -----------------------------------
|
---|
| 370 |
|
---|
| 371 | `Immutable` provides equality which treats immutable data structures as pure
|
---|
| 372 | data, performing a deep equality check if necessary.
|
---|
| 373 |
|
---|
| 374 | ```javascript
|
---|
| 375 | var map1 = Immutable.Map({a:1, b:1, c:1});
|
---|
| 376 | var map2 = Immutable.Map({a:1, b:1, c:1});
|
---|
| 377 | assert(map1 !== map2); // two different instances
|
---|
| 378 | assert(Immutable.is(map1, map2)); // have equivalent values
|
---|
| 379 | assert(map1.equals(map2)); // alternatively use the equals method
|
---|
| 380 | ```
|
---|
| 381 |
|
---|
| 382 | `Immutable.is()` uses the same measure of equality as [Object.is][]
|
---|
| 383 | including if both are immutable and all keys and values are equal
|
---|
| 384 | using the same measure of equality.
|
---|
| 385 |
|
---|
| 386 | [Object.is]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
|
---|
| 387 |
|
---|
| 388 |
|
---|
| 389 | Batching Mutations
|
---|
| 390 | ------------------
|
---|
| 391 |
|
---|
| 392 | > If a tree falls in the woods, does it make a sound?
|
---|
| 393 | >
|
---|
| 394 | > If a pure function mutates some local data in order to produce an immutable
|
---|
| 395 | > return value, is that ok?
|
---|
| 396 | >
|
---|
| 397 | > — Rich Hickey, Clojure
|
---|
| 398 |
|
---|
| 399 | Applying a mutation to create a new immutable object results in some overhead,
|
---|
| 400 | which can add up to a minor performance penalty. If you need to apply a series
|
---|
| 401 | of mutations locally before returning, `Immutable` gives you the ability to
|
---|
| 402 | create a temporary mutable (transient) copy of a collection and apply a batch of
|
---|
| 403 | mutations in a performant manner by using `withMutations`. In fact, this is
|
---|
| 404 | exactly how `Immutable` applies complex mutations itself.
|
---|
| 405 |
|
---|
| 406 | As an example, building `list2` results in the creation of 1, not 3, new
|
---|
| 407 | immutable Lists.
|
---|
| 408 |
|
---|
| 409 | ```javascript
|
---|
| 410 | var list1 = Immutable.List.of(1,2,3);
|
---|
| 411 | var list2 = list1.withMutations(function (list) {
|
---|
| 412 | list.push(4).push(5).push(6);
|
---|
| 413 | });
|
---|
| 414 | assert(list1.size === 3);
|
---|
| 415 | assert(list2.size === 6);
|
---|
| 416 | ```
|
---|
| 417 |
|
---|
| 418 | Note: `immutable` also provides `asMutable` and `asImmutable`, but only
|
---|
| 419 | encourages their use when `withMutations` will not suffice. Use caution to not
|
---|
| 420 | return a mutable copy, which could result in undesired behavior.
|
---|
| 421 |
|
---|
| 422 | *Important!*: Only a select few methods can be used in `withMutations` including
|
---|
| 423 | `set`, `push` and `pop`. These methods can be applied directly against a
|
---|
| 424 | persistent data-structure where other methods like `map`, `filter`, `sort`,
|
---|
| 425 | and `splice` will always return new immutable data-structures and never mutate
|
---|
| 426 | a mutable collection.
|
---|
| 427 |
|
---|
| 428 |
|
---|
| 429 | Documentation
|
---|
| 430 | -------------
|
---|
| 431 |
|
---|
| 432 | [Read the docs](http://facebook.github.io/immutable-js/docs/) and eat your vegetables.
|
---|
| 433 |
|
---|
| 434 | Docs are automatically generated from [Immutable.d.ts](https://github.com/facebook/immutable-js/blob/master/type-definitions/Immutable.d.ts).
|
---|
| 435 | Please contribute!
|
---|
| 436 |
|
---|
| 437 | Also, don't miss the [Wiki](https://github.com/facebook/immutable-js/wiki) which
|
---|
| 438 | contains articles on specific topics. Can't find something? Open an [issue](https://github.com/facebook/immutable-js/issues).
|
---|
| 439 |
|
---|
| 440 |
|
---|
| 441 | Testing
|
---|
| 442 | -------
|
---|
| 443 |
|
---|
| 444 | If you are using the [Chai Assertion Library](http://chaijs.com/), [Chai Immutable](https://github.com/astorije/chai-immutable) provides a set of assertions to use against `Immutable` collections.
|
---|
| 445 |
|
---|
| 446 |
|
---|
| 447 | Contribution
|
---|
| 448 | ------------
|
---|
| 449 |
|
---|
| 450 | Use [Github issues](https://github.com/facebook/immutable-js/issues) for requests.
|
---|
| 451 |
|
---|
| 452 | We actively welcome pull requests, learn how to [contribute](./CONTRIBUTING.md).
|
---|
| 453 |
|
---|
| 454 |
|
---|
| 455 | Changelog
|
---|
| 456 | ---------
|
---|
| 457 |
|
---|
| 458 | Changes are tracked as [Github releases](https://github.com/facebook/immutable-js/releases).
|
---|
| 459 |
|
---|
| 460 |
|
---|
| 461 | Thanks
|
---|
| 462 | ------
|
---|
| 463 |
|
---|
| 464 | [Phil Bagwell](https://www.youtube.com/watch?v=K2NYwP90bNs), for his inspiration
|
---|
| 465 | and research in persistent data structures.
|
---|
| 466 |
|
---|
| 467 | [Hugh Jackson](https://github.com/hughfdjackson/), for providing the npm package
|
---|
| 468 | name. If you're looking for his unsupported package, see [this repository](https://github.com/hughfdjackson/immutable).
|
---|
| 469 |
|
---|
| 470 |
|
---|
| 471 | License
|
---|
| 472 | -------
|
---|
| 473 |
|
---|
| 474 | Immutable.js is [MIT-licensed](https://github.com/facebook/immutable-js/blob/master/LICENSE).
|
---|