immutable 4.0.0-rc.5 → 4.0.0-rc.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +182 -83
- package/dist/immutable-nonambient.d.ts +951 -479
- package/dist/immutable.d.ts +951 -479
- package/dist/immutable.es.js +542 -339
- package/dist/immutable.js +555 -338
- package/dist/immutable.js.flow +331 -111
- package/dist/immutable.min.js +32 -31
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -51,44 +51,48 @@ map1.get('b') + " vs. " + map2.get('b') // 2 vs. 50
|
|
|
51
51
|
|
|
52
52
|
### Browser
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
or use a CDN such as [CDNJS](https://cdnjs.com/libraries/immutable)
|
|
56
|
-
or [jsDelivr](http://www.jsdelivr.com/#!immutable.js).
|
|
54
|
+
Immutable.js has no dependencies, which makes it predictable to include in a Browser.
|
|
57
55
|
|
|
58
|
-
|
|
56
|
+
It's highly recommended to use a module bundler like [webpack](https://webpack.github.io/),
|
|
57
|
+
[rollup](https://rollupjs.org/), or
|
|
58
|
+
[browserify](http://browserify.org/). The `immutable` npm module works
|
|
59
|
+
without any additional consideration. All examples throughout the documentation
|
|
60
|
+
will assume use of this kind of tool.
|
|
61
|
+
|
|
62
|
+
Alternatively, Immutable.js may be directly included as a script tag. Download
|
|
63
|
+
or link to a CDN such as [CDNJS](https://cdnjs.com/libraries/immutable)
|
|
64
|
+
or [jsDelivr](https://www.jsdelivr.com/package/npm/immutable).
|
|
65
|
+
|
|
66
|
+
Use a script tag to directly add `Immutable` to the global scope:
|
|
59
67
|
|
|
60
68
|
```html
|
|
61
69
|
<script src="immutable.min.js"></script>
|
|
62
70
|
<script>
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
71
|
+
var map1 = Immutable.Map({a:1, b:2, c:3});
|
|
72
|
+
var map2 = map1.set('b', 50);
|
|
73
|
+
map1.get('b'); // 2
|
|
74
|
+
map2.get('b'); // 50
|
|
67
75
|
</script>
|
|
68
76
|
```
|
|
69
77
|
|
|
70
|
-
Or use an AMD loader (such as [RequireJS](http://requirejs.org/)):
|
|
78
|
+
Or use an AMD-style loader (such as [RequireJS](http://requirejs.org/)):
|
|
71
79
|
|
|
72
80
|
```js
|
|
73
81
|
require(['./immutable.min.js'], function (Immutable) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
82
|
+
var map1 = Immutable.Map({a:1, b:2, c:3});
|
|
83
|
+
var map2 = map1.set('b', 50);
|
|
84
|
+
map1.get('b'); // 2
|
|
85
|
+
map2.get('b'); // 50
|
|
78
86
|
});
|
|
79
87
|
```
|
|
80
88
|
|
|
81
|
-
If you're using [webpack](https://webpack.github.io/) or
|
|
82
|
-
[browserify](http://browserify.org/), the `immutable` npm module also works
|
|
83
|
-
from the browser.
|
|
84
|
-
|
|
85
89
|
### Flow & TypeScript
|
|
86
90
|
|
|
87
91
|
Use these Immutable collections and sequences as you would use native
|
|
88
92
|
collections in your [Flowtype](https://flowtype.org/) or [TypeScript](http://typescriptlang.org) programs while still taking
|
|
89
93
|
advantage of type generics, error detection, and auto-complete in your IDE.
|
|
90
94
|
|
|
91
|
-
Installing `immutable` via npm brings with it type definitions for Flow (v0.
|
|
95
|
+
Installing `immutable` via npm brings with it type definitions for Flow (v0.55.0 or higher)
|
|
92
96
|
and TypeScript (v2.1.0 or higher), so you shouldn't need to do anything at all!
|
|
93
97
|
|
|
94
98
|
#### Using TypeScript with Immutable.js v4
|
|
@@ -231,7 +235,7 @@ alpha.map((v, k) => k.toUpperCase()).join();
|
|
|
231
235
|
// 'A,B,C,D'
|
|
232
236
|
```
|
|
233
237
|
|
|
234
|
-
###
|
|
238
|
+
### Convert from raw JavaScript objects and arrays.
|
|
235
239
|
|
|
236
240
|
Designed to inter-operate with your existing JavaScript, Immutable.js
|
|
237
241
|
accepts plain JavaScript Arrays and Objects anywhere a method expects an
|
|
@@ -239,12 +243,17 @@ accepts plain JavaScript Arrays and Objects anywhere a method expects an
|
|
|
239
243
|
|
|
240
244
|
<!-- runkit:activate -->
|
|
241
245
|
```js
|
|
242
|
-
const { Map } = require('immutable')
|
|
246
|
+
const { Map, List } = require('immutable')
|
|
243
247
|
const map1 = Map({ a: 1, b: 2, c: 3, d: 4 })
|
|
244
248
|
const map2 = Map({ c: 10, a: 20, t: 30 })
|
|
245
249
|
const obj = { d: 100, o: 200, g: 300 }
|
|
246
250
|
const map3 = map1.merge(map2, obj);
|
|
247
251
|
// Map { a: 20, b: 2, c: 10, d: 100, t: 30, o: 200, g: 300 }
|
|
252
|
+
const list1 = List([ 1, 2, 3 ])
|
|
253
|
+
const list2 = List([ 4, 5, 6 ])
|
|
254
|
+
const array = [ 7, 8, 9 ]
|
|
255
|
+
const list3 = list1.concat(list2, array)
|
|
256
|
+
// List [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
|
|
248
257
|
```
|
|
249
258
|
|
|
250
259
|
This is possible because Immutable.js can treat any JavaScript Array or Object
|
|
@@ -317,6 +326,19 @@ const mapped = foo.map(x => x * x);
|
|
|
317
326
|
var mapped = foo.map(function (x) { return x * x; });
|
|
318
327
|
```
|
|
319
328
|
|
|
329
|
+
All Immutable.js collections are [Iterable][Iterators], which allows them to be
|
|
330
|
+
used anywhere an Iterable is expected, such as when spreading into an Array.
|
|
331
|
+
|
|
332
|
+
<!-- runkit:activate -->
|
|
333
|
+
```js
|
|
334
|
+
const { List } = require('immutable')
|
|
335
|
+
const aList = List([ 1, 2, 3 ])
|
|
336
|
+
const anArray = [ 0, ...aList, 4, 5 ] // [ 0, 1, 2, 3, 4, 5 ]
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Note: A Collection is always iterated in the same order, however that order may
|
|
340
|
+
not always be well defined, as is the case for the `Map` and `Set`.
|
|
341
|
+
|
|
320
342
|
[Iterators]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/The_Iterator_protocol
|
|
321
343
|
[Arrow Functions]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
|
|
322
344
|
[Classes]: http://wiki.ecmascript.org/doku.php?id=strawman:maximally_minimal_classes
|
|
@@ -359,93 +381,100 @@ const nested4 = nested3.updateIn([ 'a', 'b', 'c' ], list => list.push(6))
|
|
|
359
381
|
```
|
|
360
382
|
|
|
361
383
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
`Seq` describes a lazy operation, allowing them to efficiently chain
|
|
366
|
-
use of all the sequence methods (such as `map` and `filter`).
|
|
367
|
-
|
|
368
|
-
**Seq is immutable** — Once a Seq is created, it cannot be
|
|
369
|
-
changed, appended to, rearranged or otherwise modified. Instead, any mutative
|
|
370
|
-
method called on a Seq will return a new Seq.
|
|
384
|
+
Equality treats Collections as Values
|
|
385
|
+
-------------------------------------
|
|
371
386
|
|
|
372
|
-
|
|
373
|
-
|
|
387
|
+
Immutable.js collections are treated as pure data *values*. Two immutable
|
|
388
|
+
collections are considered *value equal* (via `.equals()` or `is()`) if they
|
|
389
|
+
represent the same collection of values. This differs from JavaScript's typical
|
|
390
|
+
*reference equal* (via `===` or `==`) for Objects and Arrays which only
|
|
391
|
+
determines if two variables represent references to the same object instance.
|
|
374
392
|
|
|
375
|
-
|
|
376
|
-
|
|
393
|
+
Consider the example below where two identical `Map` instances are not
|
|
394
|
+
*reference equal* but are *value equal*.
|
|
377
395
|
|
|
396
|
+
<!-- runkit:activate -->
|
|
378
397
|
```js
|
|
379
|
-
|
|
380
|
-
const
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
Once the Seq is used, it performs only the work necessary. In this
|
|
386
|
-
example, no intermediate arrays are ever created, filter is called three times,
|
|
387
|
-
and map is only called once:
|
|
398
|
+
// First consider:
|
|
399
|
+
const obj1 = { a: 1, b: 2, c: 3 }
|
|
400
|
+
const obj2 = { a: 1, b: 2, c: 3 }
|
|
401
|
+
obj1 !== obj2 // two different instances are always not equal with ===
|
|
388
402
|
|
|
389
|
-
|
|
390
|
-
|
|
403
|
+
const { Map, is } = require('immutable')
|
|
404
|
+
const map1 = Map({ a: 1, b: 2, c: 3 })
|
|
405
|
+
const map2 = Map({ a: 1, b: 2, c: 3 })
|
|
406
|
+
map1 !== map2 // two different instances are not reference-equal
|
|
407
|
+
map1.equals(map2) // but are value-equal if they have the same values
|
|
408
|
+
is(map1, map2) // alternatively can use the is() function
|
|
391
409
|
```
|
|
392
410
|
|
|
393
|
-
|
|
411
|
+
Value equality allows Immutable.js collections to be used as keys in Maps or
|
|
412
|
+
values in Sets, and retrieved with different but equivalent collections:
|
|
394
413
|
|
|
395
414
|
<!-- runkit:activate -->
|
|
396
415
|
```js
|
|
397
|
-
const { Map } = require('immutable')
|
|
398
|
-
const
|
|
416
|
+
const { Map, Set } = require('immutable')
|
|
417
|
+
const map1 = Map({ a: 1, b: 2, c: 3 })
|
|
418
|
+
const map2 = Map({ a: 1, b: 2, c: 3 })
|
|
419
|
+
const set = Set().add(map1)
|
|
420
|
+
set.has(map2) // true because these are value-equal
|
|
399
421
|
```
|
|
400
422
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
seq.flip().map(key => key.toUpperCase()).flip().toObject();
|
|
406
|
-
// { A: 1, B: 2, C: 3 }
|
|
407
|
-
```
|
|
423
|
+
Note: `is()` uses the same measure of equality as [Object.is][] for scalar
|
|
424
|
+
strings and numbers, but uses value equality for Immutable collections,
|
|
425
|
+
determining if both are immutable and all keys and values are equal
|
|
426
|
+
using the same measure of equality.
|
|
408
427
|
|
|
409
|
-
|
|
428
|
+
[Object.is]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
|
|
410
429
|
|
|
411
|
-
|
|
412
|
-
```js
|
|
413
|
-
const { Range } = require('immutable')
|
|
414
|
-
Range(1, Infinity)
|
|
415
|
-
.skip(1000)
|
|
416
|
-
.map(n => -n)
|
|
417
|
-
.filter(n => n % 2 === 0)
|
|
418
|
-
.take(2)
|
|
419
|
-
.reduce((r, n) => r * n, 1);
|
|
420
|
-
// 1006008
|
|
421
|
-
```
|
|
430
|
+
#### Performance tradeoffs
|
|
422
431
|
|
|
423
|
-
|
|
424
|
-
|
|
432
|
+
While value equality is useful in many circumstances, it has different
|
|
433
|
+
performance characteristics than reference equality. Understanding these
|
|
434
|
+
tradeoffs may help you decide which to use in each case, especially when used
|
|
435
|
+
to memoize some operation.
|
|
425
436
|
|
|
437
|
+
When comparing two collections, value equality may require considering every
|
|
438
|
+
item in each collection, on an `O(N)` time complexity. For large collections of
|
|
439
|
+
values, this could become a costly operation. Though if the two are not equal
|
|
440
|
+
and hardly similar, the inequality is determined very quickly. In contrast, when
|
|
441
|
+
comparing two collections with reference equality, only the initial references
|
|
442
|
+
to memory need to be compared which is not based on the size of the collections,
|
|
443
|
+
which has an `O(1)` time complexity. Checking reference equality is always very
|
|
444
|
+
fast, however just because two collections are not reference-equal does not rule
|
|
445
|
+
out the possibility that they may be value-equal.
|
|
426
446
|
|
|
427
|
-
|
|
428
|
-
-----------------------------------
|
|
447
|
+
#### Return self on no-op optimization
|
|
429
448
|
|
|
430
|
-
Immutable.js
|
|
431
|
-
|
|
449
|
+
When possible, Immutable.js avoids creating new objects for updates where no
|
|
450
|
+
change in *value* occurred, to allow for efficient *reference equality* checking
|
|
451
|
+
to quickly determine if no change occurred.
|
|
432
452
|
|
|
433
453
|
<!-- runkit:activate -->
|
|
434
454
|
```js
|
|
435
|
-
const { Map
|
|
436
|
-
const
|
|
437
|
-
const
|
|
438
|
-
|
|
439
|
-
assert.equal(is(map1, map2), true) // have equivalent values
|
|
440
|
-
assert.equal(map1.equals(map2), true) // alternatively use the equals method
|
|
455
|
+
const { Map } = require('immutable')
|
|
456
|
+
const originalMap = Map({ a: 1, b: 2, c: 3 })
|
|
457
|
+
const updatedMap = originalMap.set('b', 2)
|
|
458
|
+
updatedMap === originalMap // No-op .set() returned the original reference.
|
|
441
459
|
```
|
|
442
460
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
[Object.is]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
|
|
461
|
+
However updates which do result in a change will return a new reference. Each
|
|
462
|
+
of these operations occur independently, so two similar updates will not return
|
|
463
|
+
the same reference:
|
|
448
464
|
|
|
465
|
+
<!-- runkit:activate -->
|
|
466
|
+
```js
|
|
467
|
+
const { Map } = require('immutable')
|
|
468
|
+
const originalMap = Map({ a: 1, b: 2, c: 3 })
|
|
469
|
+
const updatedMap = originalMap.set('b', 1000)
|
|
470
|
+
// New instance, leaving the original immutable.
|
|
471
|
+
updatedMap !== originalMap
|
|
472
|
+
const anotherUpdatedMap = originalMap.set('b', 1000)
|
|
473
|
+
// Despite both the results of the same operation, each created a new reference.
|
|
474
|
+
anotherUpdatedMap !== updatedMap
|
|
475
|
+
// However the two are value equal.
|
|
476
|
+
anotherUpdatedMap.equals(updatedMap)
|
|
477
|
+
```
|
|
449
478
|
|
|
450
479
|
Batching Mutations
|
|
451
480
|
------------------
|
|
@@ -489,6 +518,76 @@ and `splice` will always return new immutable data-structures and never mutate
|
|
|
489
518
|
a mutable collection.
|
|
490
519
|
|
|
491
520
|
|
|
521
|
+
Lazy Seq
|
|
522
|
+
--------
|
|
523
|
+
|
|
524
|
+
`Seq` describes a lazy operation, allowing them to efficiently chain
|
|
525
|
+
use of all the higher-order collection methods (such as `map` and `filter`)
|
|
526
|
+
by not creating intermediate collections.
|
|
527
|
+
|
|
528
|
+
**Seq is immutable** — Once a Seq is created, it cannot be
|
|
529
|
+
changed, appended to, rearranged or otherwise modified. Instead, any mutative
|
|
530
|
+
method called on a `Seq` will return a new `Seq`.
|
|
531
|
+
|
|
532
|
+
**Seq is lazy** — `Seq` does as little work as necessary to respond to any
|
|
533
|
+
method call. Values are often created during iteration, including implicit
|
|
534
|
+
iteration when reducing or converting to a concrete data structure such as
|
|
535
|
+
a `List` or JavaScript `Array`.
|
|
536
|
+
|
|
537
|
+
For example, the following performs no work, because the resulting
|
|
538
|
+
`Seq`'s values are never iterated:
|
|
539
|
+
|
|
540
|
+
```js
|
|
541
|
+
const { Seq } = require('immutable')
|
|
542
|
+
const oddSquares = Seq([ 1, 2, 3, 4, 5, 6, 7, 8 ])
|
|
543
|
+
.filter(x => x % 2 !== 0)
|
|
544
|
+
.map(x => x * x)
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
Once the `Seq` is used, it performs only the work necessary. In this
|
|
548
|
+
example, no intermediate arrays are ever created, filter is called three
|
|
549
|
+
times, and map is only called once:
|
|
550
|
+
|
|
551
|
+
```js
|
|
552
|
+
oddSquares.get(1); // 9
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
Any collection can be converted to a lazy Seq with `Seq()`.
|
|
556
|
+
|
|
557
|
+
<!-- runkit:activate -->
|
|
558
|
+
```js
|
|
559
|
+
const { Map } = require('immutable')
|
|
560
|
+
const map = Map({ a: 1, b: 2, c: 3 }
|
|
561
|
+
const lazySeq = Seq(map)
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
`Seq` allows for the efficient chaining of operations, allowing for the
|
|
565
|
+
expression of logic that can otherwise be very tedious:
|
|
566
|
+
|
|
567
|
+
```js
|
|
568
|
+
lazySeq
|
|
569
|
+
.flip()
|
|
570
|
+
.map(key => key.toUpperCase())
|
|
571
|
+
.flip()
|
|
572
|
+
// Seq { A: 1, B: 1, C: 1 }
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
As well as expressing logic that would otherwise seem memory or time
|
|
576
|
+
limited, for example `Range` is a special kind of Lazy sequence.
|
|
577
|
+
|
|
578
|
+
<!-- runkit:activate -->
|
|
579
|
+
```js
|
|
580
|
+
const { Range } = require('immutable')
|
|
581
|
+
Range(1, Infinity)
|
|
582
|
+
.skip(1000)
|
|
583
|
+
.map(n => -n)
|
|
584
|
+
.filter(n => n % 2 === 0)
|
|
585
|
+
.take(2)
|
|
586
|
+
.reduce((r, n) => r * n, 1)
|
|
587
|
+
// 1006008
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
|
|
492
591
|
Documentation
|
|
493
592
|
-------------
|
|
494
593
|
|