{"id":2223069,"url":"https://facebook.github.io/immutable-js","last_synced_at":"2025-07-16T01:31:27.755Z","repository":{"id":18256937,"uuid":"21413198","full_name":"immutable-js/immutable-js","owner":"immutable-js","description":"Immutable persistent data collections for Javascript which increase efficiency and simplicity.","archived":false,"fork":false,"pushed_at":"2024-11-19T21:29:05.000Z","size":71422,"stargazers_count":32955,"open_issues_count":116,"forks_count":1786,"subscribers_count":501,"default_branch":"main","last_synced_at":"2024-11-20T07:25:25.851Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://immutable-js.com","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/immutable-js.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["jdeniau","Methuselah96"]}},"created_at":"2014-07-02T06:02:29.000Z","updated_at":"2024-11-20T06:55:08.000Z","dependencies_parsed_at":"2024-01-12T04:58:01.752Z","dependency_job_id":"98842a57-c87d-437f-892b-7777b82350f7","html_url":"https://github.com/immutable-js/immutable-js","commit_stats":{"total_commits":1610,"total_committers":228,"mean_commits":7.06140350877193,"dds":"0.32795031055900625","last_synced_commit":"81a9175439ae220ab80c816b003d2322e006eb13"},"previous_names":["facebook/immutable-js"],"tags_count":92,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/immutable-js%2Fimmutable-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/immutable-js%2Fimmutable-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/immutable-js%2Fimmutable-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/immutable-js%2Fimmutable-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/immutable-js","download_url":"https://codeload.github.com/immutable-js/immutable-js/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226089891,"owners_count":17572112,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-01-22T16:03:02.991Z","updated_at":"2025-07-16T01:31:27.740Z","avatar_url":"https://github.com/immutable-js.png","language":"TypeScript","readme":"# Immutable collections for JavaScript\n\n[![Build Status](https://github.com/immutable-js/immutable-js/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/immutable-js/immutable-js/actions/workflows/ci.yml?query=branch%3Amain) [Chat on slack](https://immutable-js.slack.com)\n\n[Read the docs](https://immutable-js.com/docs/) and eat your vegetables.\n\nDocs are automatically generated from [README.md][] and [immutable.d.ts][].\nPlease contribute! Also, don't miss the [wiki][] which contains articles on\nadditional specific topics. Can't find something? Open an [issue][].\n\n**Table of contents:**\n\n- [Introduction](#introduction)\n- [Getting started](#getting-started)\n- [The case for Immutability](#the-case-for-immutability)\n- [JavaScript-first API](#javascript-first-api)\n- [Nested Structures](#nested-structures)\n- [Equality treats Collections as Values](#equality-treats-collections-as-values)\n- [Batching Mutations](#batching-mutations)\n- [Lazy Seq](#lazy-seq)\n- [Additional Tools and Resources](#additional-tools-and-resources)\n- [Contributing](#contributing)\n\n## Introduction\n\n[Immutable][] data cannot be changed once created, leading to much simpler\napplication development, no defensive copying, and enabling advanced memoization\nand change detection techniques with simple logic. [Persistent][] data presents\na mutative API which does not update the data in-place, but instead always\nyields new updated data.\n\nImmutable.js provides many Persistent Immutable data structures including:\n`List`, `Stack`, `Map`, `OrderedMap`, `Set`, `OrderedSet` and `Record`.\n\nThese data structures are highly efficient on modern JavaScript VMs by using\nstructural sharing via [hash maps tries][] and [vector tries][] as popularized\nby Clojure and Scala, minimizing the need to copy or cache data.\n\nImmutable.js also provides a lazy `Seq`, allowing efficient\nchaining of collection methods like `map` and `filter` without creating\nintermediate representations. Create some `Seq` with `Range` and `Repeat`.\n\nWant to hear more? Watch the presentation about Immutable.js:\n\n[![Immutable Data and React](website/public/Immutable-Data-and-React-YouTube.png)](https://youtu.be/I7IdS-PbEgI)\n\n[README.md]: https://github.com/immutable-js/immutable-js/blob/main/README.md\n[immutable.d.ts]: https://github.com/immutable-js/immutable-js/blob/main/type-definitions/immutable.d.ts\n[wiki]: https://github.com/immutable-js/immutable-js/wiki\n[issue]: https://github.com/immutable-js/immutable-js/issues\n[Persistent]: https://en.wikipedia.org/wiki/Persistent_data_structure\n[Immutable]: https://en.wikipedia.org/wiki/Immutable_object\n[hash maps tries]: https://en.wikipedia.org/wiki/Hash_array_mapped_trie\n[vector tries]: https://hypirion.com/musings/understanding-persistent-vector-pt-1\n\n## Getting started\n\nInstall `immutable` using npm.\n\n```shell\n# using npm\nnpm install immutable\n\n# using Yarn\nyarn add immutable\n\n# using pnpm\npnpm add immutable\n\n# using Bun\nbun add immutable\n```\n\nThen require it into any module.\n\n```js\nimport { Map } from 'immutable';\nconst map1 = Map({ a: 1, b: 2, c: 3 });\nconst map2 = map1.set('b', 50);\nmap1.get('b') + ' vs. ' + map2.get('b'); // 2 vs. 50\n```\n\n### Browser\n\nImmutable.js has no dependencies, which makes it predictable to include in a Browser.\n\nIt's highly recommended to use a module bundler like [webpack](https://webpack.js.org/),\n[rollup](https://rollupjs.org/), or\n[browserify](https://browserify.org/). The `immutable` npm module works\nwithout any additional consideration. All examples throughout the documentation\nwill assume use of this kind of tool.\n\nAlternatively, Immutable.js may be directly included as a script tag. Download\nor link to a CDN such as [CDNJS](https://cdnjs.com/libraries/immutable)\nor [jsDelivr](https://www.jsdelivr.com/package/npm/immutable).\n\nUse a script tag to directly add `Immutable` to the global scope:\n\n```html\n\u003cscript src=\"immutable.min.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n  var map1 = Immutable.Map({ a: 1, b: 2, c: 3 });\n  var map2 = map1.set('b', 50);\n  map1.get('b'); // 2\n  map2.get('b'); // 50\n\u003c/script\u003e\n```\n\nOr use an AMD-style loader (such as [RequireJS](https://requirejs.org/)):\n\n```js\nrequire(['./immutable.min.js'], function (Immutable) {\n  var map1 = Immutable.Map({ a: 1, b: 2, c: 3 });\n  var map2 = map1.set('b', 50);\n  map1.get('b'); // 2\n  map2.get('b'); // 50\n});\n```\n\n### Flow \u0026 TypeScript\n\nUse these Immutable collections and sequences as you would use native\ncollections in your [Flowtype](https://flowtype.org/) or [TypeScript](https://typescriptlang.org) programs while still taking\nadvantage of type generics, error detection, and auto-complete in your IDE.\n\nInstalling `immutable` via npm brings with it type definitions for Flow (v0.55.0 or higher)\nand TypeScript (v4.5 or higher), so you shouldn't need to do anything at all!\n\n#### Using TypeScript with Immutable.js v4+\n\nImmutable.js type definitions embrace ES2015. While Immutable.js itself supports\nlegacy browsers and environments, its type definitions require TypeScript's 2015\nlib. Include either `\"target\": \"es2015\"` or `\"lib\": \"es2015\"` in your\n`tsconfig.json`, or provide `--target es2015` or `--lib es2015` to the\n`tsc` command.\n\n```js\nimport { Map } from 'immutable';\nconst map1 = Map({ a: 1, b: 2, c: 3 });\nconst map2 = map1.set('b', 50);\nmap1.get('b') + ' vs. ' + map2.get('b'); // 2 vs. 50\n```\n\n#### Using TypeScript with Immutable.js v3 and earlier:\n\nPrevious versions of Immutable.js include a reference file which you can include\nvia relative path to the type definitions at the top of your file.\n\n```js\n///\u003creference path='./node_modules/immutable/dist/immutable.d.ts'/\u003e\nimport { Map } from 'immutable';\nvar map1: Map\u003cstring, number\u003e;\nmap1 = Map({ a: 1, b: 2, c: 3 });\nvar map2 = map1.set('b', 50);\nmap1.get('b'); // 2\nmap2.get('b'); // 50\n```\n\n## The case for Immutability\n\nMuch of what makes application development difficult is tracking mutation and\nmaintaining state. Developing with immutable data encourages you to think\ndifferently about how data flows through your application.\n\nSubscribing to data events throughout your application creates a huge overhead of\nbook-keeping which can hurt performance, sometimes dramatically, and creates\nopportunities for areas of your application to get out of sync with each other\ndue to easy to make programmer error. Since immutable data never changes,\nsubscribing to changes throughout the model is a dead-end and new data can only\never be passed from above.\n\nThis model of data flow aligns well with the architecture of [React][]\nand especially well with an application designed using the ideas of [Flux][].\n\nWhen data is passed from above rather than being subscribed to, and you're only\ninterested in doing work when something has changed, you can use equality.\n\nImmutable collections should be treated as _values_ rather than _objects_. While\nobjects represent some thing which could change over time, a value represents\nthe state of that thing at a particular instance of time. This principle is most\nimportant to understanding the appropriate use of immutable data. In order to\ntreat Immutable.js collections as values, it's important to use the\n`Immutable.is()` function or `.equals()` method to determine _value equality_\ninstead of the `===` operator which determines object _reference identity_.\n\n```js\nimport { Map } from 'immutable';\nconst map1 = Map({ a: 1, b: 2, c: 3 });\nconst map2 = Map({ a: 1, b: 2, c: 3 });\nmap1.equals(map2); // true\nmap1 === map2; // false\n```\n\nNote: As a performance optimization Immutable.js attempts to return the existing\ncollection when an operation would result in an identical collection, allowing\nfor using `===` reference equality to determine if something definitely has not\nchanged. This can be extremely useful when used within a memoization function\nwhich would prefer to re-run the function if a deeper equality check could\npotentially be more costly. The `===` equality check is also used internally by\n`Immutable.is` and `.equals()` as a performance optimization.\n\n```js\nimport { Map } from 'immutable';\nconst map1 = Map({ a: 1, b: 2, c: 3 });\nconst map2 = map1.set('b', 2); // Set to same value\nmap1 === map2; // true\n```\n\nIf an object is immutable, it can be \"copied\" simply by making another reference\nto it instead of copying the entire object. Because a reference is much smaller\nthan the object itself, this results in memory savings and a potential boost in\nexecution speed for programs which rely on copies (such as an undo-stack).\n\n```js\nimport { Map } from 'immutable';\nconst map = Map({ a: 1, b: 2, c: 3 });\nconst mapCopy = map; // Look, \"copies\" are free!\n```\n\n[React]: https://reactjs.org/\n[Flux]: https://facebook.github.io/flux/docs/in-depth-overview/\n\n## JavaScript-first API\n\nWhile Immutable.js is inspired by Clojure, Scala, Haskell and other functional\nprogramming environments, it's designed to bring these powerful concepts to\nJavaScript, and therefore has an Object-Oriented API that closely mirrors that\nof [ES2015][] [Array][], [Map][], and [Set][].\n\n[es2015]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla\n[array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array\n[map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map\n[set]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set\n\nThe difference for the immutable collections is that methods which would mutate\nthe collection, like `push`, `set`, `unshift` or `splice`, instead return a new\nimmutable collection. Methods which return new arrays, like `slice` or `concat`,\ninstead return new immutable collections.\n\n```js\nimport { List } from 'immutable';\nconst list1 = List([1, 2]);\nconst list2 = list1.push(3, 4, 5);\nconst list3 = list2.unshift(0);\nconst list4 = list1.concat(list2, list3);\nassert.equal(list1.size, 2);\nassert.equal(list2.size, 5);\nassert.equal(list3.size, 6);\nassert.equal(list4.size, 13);\nassert.equal(list4.get(0), 1);\n```\n\nAlmost all of the methods on [Array][] will be found in similar form on\n`Immutable.List`, those of [Map][] found on `Immutable.Map`, and those of [Set][]\nfound on `Immutable.Set`, including collection operations like `forEach()`\nand `map()`.\n\n```js\nimport { Map } from 'immutable';\nconst alpha = Map({ a: 1, b: 2, c: 3, d: 4 });\nalpha.map((v, k) =\u003e k.toUpperCase()).join();\n// 'A,B,C,D'\n```\n\n### Convert from raw JavaScript objects and arrays.\n\nDesigned to inter-operate with your existing JavaScript, Immutable.js\naccepts plain JavaScript Arrays and Objects anywhere a method expects a\n`Collection`.\n\n```js\nimport { Map, List } from 'immutable';\nconst map1 = Map({ a: 1, b: 2, c: 3, d: 4 });\nconst map2 = Map({ c: 10, a: 20, t: 30 });\nconst obj = { d: 100, o: 200, g: 300 };\nconst map3 = map1.merge(map2, obj);\n// Map { a: 20, b: 2, c: 10, d: 100, t: 30, o: 200, g: 300 }\nconst list1 = List([1, 2, 3]);\nconst list2 = List([4, 5, 6]);\nconst array = [7, 8, 9];\nconst list3 = list1.concat(list2, array);\n// List [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]\n```\n\nThis is possible because Immutable.js can treat any JavaScript Array or Object\nas a Collection. You can take advantage of this in order to get sophisticated\ncollection methods on JavaScript Objects, which otherwise have a very sparse\nnative API. Because Seq evaluates lazily and does not cache intermediate\nresults, these operations can be extremely efficient.\n\n```js\nimport { Seq } from 'immutable';\nconst myObject = { a: 1, b: 2, c: 3 };\nSeq(myObject)\n  .map((x) =\u003e x * x)\n  .toObject();\n// { a: 1, b: 4, c: 9 }\n```\n\nKeep in mind, when using JS objects to construct Immutable Maps, that\nJavaScript Object properties are always strings, even if written in a quote-less\nshorthand, while Immutable Maps accept keys of any type.\n\n```js\nimport { fromJS } from 'immutable';\n\nconst obj = { 1: 'one' };\nconsole.log(Object.keys(obj)); // [ \"1\" ]\nconsole.log(obj['1'], obj[1]); // \"one\", \"one\"\n\nconst map = fromJS(obj);\nconsole.log(map.get('1'), map.get(1)); // \"one\", undefined\n```\n\nProperty access for JavaScript Objects first converts the key to a string, but\nsince Immutable Map keys can be of any type the argument to `get()` is\nnot altered.\n\n### Converts back to raw JavaScript objects.\n\nAll Immutable.js Collections can be converted to plain JavaScript Arrays and\nObjects shallowly with `toArray()` and `toObject()` or deeply with `toJS()`.\nAll Immutable Collections also implement `toJSON()` allowing them to be passed\nto `JSON.stringify` directly. They also respect the custom `toJSON()` methods of\nnested objects.\n\n```js\nimport { Map, List } from 'immutable';\nconst deep = Map({ a: 1, b: 2, c: List([3, 4, 5]) });\nconsole.log(deep.toObject()); // { a: 1, b: 2, c: List [ 3, 4, 5 ] }\nconsole.log(deep.toArray()); // [ 1, 2, List [ 3, 4, 5 ] ]\nconsole.log(deep.toJS()); // { a: 1, b: 2, c: [ 3, 4, 5 ] }\nJSON.stringify(deep); // '{\"a\":1,\"b\":2,\"c\":[3,4,5]}'\n```\n\n### Embraces ES2015\n\nImmutable.js supports all JavaScript environments, including legacy\nbrowsers (even IE11). However it also takes advantage of features added to\nJavaScript in [ES2015][], the latest standard version of JavaScript, including\n[Iterators][], [Arrow Functions][], [Classes][], and [Modules][]. It's inspired\nby the native [Map][] and [Set][] collections added to ES2015.\n\nAll examples in the Documentation are presented in ES2015. To run in all\nbrowsers, they need to be translated to ES5.\n\n```js\n// ES2015\nconst mapped = foo.map((x) =\u003e x * x);\n// ES5\nvar mapped = foo.map(function (x) {\n  return x * x;\n});\n```\n\nAll Immutable.js collections are [Iterable][iterators], which allows them to be\nused anywhere an Iterable is expected, such as when spreading into an Array.\n\n```js\nimport { List } from 'immutable';\nconst aList = List([1, 2, 3]);\nconst anArray = [0, ...aList, 4, 5]; // [ 0, 1, 2, 3, 4, 5 ]\n```\n\nNote: A Collection is always iterated in the same order, however that order may\nnot always be well defined, as is the case for the `Map` and `Set`.\n\n[Iterators]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/The_Iterator_protocol\n[Arrow Functions]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions\n[Classes]: https://wiki.ecmascript.org/doku.php?id=strawman:maximally_minimal_classes\n[Modules]: https://www.2ality.com/2014/09/es6-modules-final.html\n\n## Nested Structures\n\nThe collections in Immutable.js are intended to be nested, allowing for deep\ntrees of data, similar to JSON.\n\n```js\nimport { fromJS } from 'immutable';\nconst nested = fromJS({ a: { b: { c: [3, 4, 5] } } });\n// Map { a: Map { b: Map { c: List [ 3, 4, 5 ] } } }\n```\n\nA few power-tools allow for reading and operating on nested data. The\nmost useful are `mergeDeep`, `getIn`, `setIn`, and `updateIn`, found on `List`,\n`Map` and `OrderedMap`.\n\n```js\nimport { fromJS } from 'immutable';\nconst nested = fromJS({ a: { b: { c: [3, 4, 5] } } });\n\nconst nested2 = nested.mergeDeep({ a: { b: { d: 6 } } });\n// Map { a: Map { b: Map { c: List [ 3, 4, 5 ], d: 6 } } }\n\nconsole.log(nested2.getIn(['a', 'b', 'd'])); // 6\n\nconst nested3 = nested2.updateIn(['a', 'b', 'd'], (value) =\u003e value + 1);\nconsole.log(nested3);\n// Map { a: Map { b: Map { c: List [ 3, 4, 5 ], d: 7 } } }\n\nconst nested4 = nested3.updateIn(['a', 'b', 'c'], (list) =\u003e list.push(6));\n// Map { a: Map { b: Map { c: List [ 3, 4, 5, 6 ], d: 7 } } }\n```\n\n## Equality treats Collections as Values\n\nImmutable.js collections are treated as pure data _values_. Two immutable\ncollections are considered _value equal_ (via `.equals()` or `is()`) if they\nrepresent the same collection of values. This differs from JavaScript's typical\n_reference equal_ (via `===` or `==`) for Objects and Arrays which only\ndetermines if two variables represent references to the same object instance.\n\nConsider the example below where two identical `Map` instances are not\n_reference equal_ but are _value equal_.\n\n```js\n// First consider:\nconst obj1 = { a: 1, b: 2, c: 3 };\nconst obj2 = { a: 1, b: 2, c: 3 };\nobj1 !== obj2; // two different instances are always not equal with ===\n\nimport { Map, is } from 'immutable';\nconst map1 = Map({ a: 1, b: 2, c: 3 });\nconst map2 = Map({ a: 1, b: 2, c: 3 });\nmap1 !== map2; // two different instances are not reference-equal\nmap1.equals(map2); // but are value-equal if they have the same values\nis(map1, map2); // alternatively can use the is() function\n```\n\nValue equality allows Immutable.js collections to be used as keys in Maps or\nvalues in Sets, and retrieved with different but equivalent collections:\n\n```js\nimport { Map, Set } from 'immutable';\nconst map1 = Map({ a: 1, b: 2, c: 3 });\nconst map2 = Map({ a: 1, b: 2, c: 3 });\nconst set = Set().add(map1);\nset.has(map2); // true because these are value-equal\n```\n\nNote: `is()` uses the same measure of equality as [Object.is][] for scalar\nstrings and numbers, but uses value equality for Immutable collections,\ndetermining if both are immutable and all keys and values are equal\nusing the same measure of equality.\n\n[object.is]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n\n#### Performance tradeoffs\n\nWhile value equality is useful in many circumstances, it has different\nperformance characteristics than reference equality. Understanding these\ntradeoffs may help you decide which to use in each case, especially when used\nto memoize some operation.\n\nWhen comparing two collections, value equality may require considering every\nitem in each collection, on an `O(N)` time complexity. For large collections of\nvalues, this could become a costly operation. Though if the two are not equal\nand hardly similar, the inequality is determined very quickly. In contrast, when\ncomparing two collections with reference equality, only the initial references\nto memory need to be compared which is not based on the size of the collections,\nwhich has an `O(1)` time complexity. Checking reference equality is always very\nfast, however just because two collections are not reference-equal does not rule\nout the possibility that they may be value-equal.\n\n#### Return self on no-op optimization\n\nWhen possible, Immutable.js avoids creating new objects for updates where no\nchange in _value_ occurred, to allow for efficient _reference equality_ checking\nto quickly determine if no change occurred.\n\n```js\nimport { Map } from 'immutable';\nconst originalMap = Map({ a: 1, b: 2, c: 3 });\nconst updatedMap = originalMap.set('b', 2);\nupdatedMap === originalMap; // No-op .set() returned the original reference.\n```\n\nHowever updates which do result in a change will return a new reference. Each\nof these operations occur independently, so two similar updates will not return\nthe same reference:\n\n```js\nimport { Map } from 'immutable';\nconst originalMap = Map({ a: 1, b: 2, c: 3 });\nconst updatedMap = originalMap.set('b', 1000);\n// New instance, leaving the original immutable.\nupdatedMap !== originalMap;\nconst anotherUpdatedMap = originalMap.set('b', 1000);\n// Despite both the results of the same operation, each created a new reference.\nanotherUpdatedMap !== updatedMap;\n// However the two are value equal.\nanotherUpdatedMap.equals(updatedMap);\n```\n\n## Batching Mutations\n\n\u003e If a tree falls in the woods, does it make a sound?\n\u003e\n\u003e If a pure function mutates some local data in order to produce an immutable\n\u003e return value, is that ok?\n\u003e\n\u003e — Rich Hickey, Clojure\n\nApplying a mutation to create a new immutable object results in some overhead,\nwhich can add up to a minor performance penalty. If you need to apply a series\nof mutations locally before returning, Immutable.js gives you the ability to\ncreate a temporary mutable (transient) copy of a collection and apply a batch of\nmutations in a performant manner by using `withMutations`. In fact, this is\nexactly how Immutable.js applies complex mutations itself.\n\nAs an example, building `list2` results in the creation of 1, not 3, new\nimmutable Lists.\n\n```js\nimport { List } from 'immutable';\nconst list1 = List([1, 2, 3]);\nconst list2 = list1.withMutations(function (list) {\n  list.push(4).push(5).push(6);\n});\nassert.equal(list1.size, 3);\nassert.equal(list2.size, 6);\n```\n\nNote: Immutable.js also provides `asMutable` and `asImmutable`, but only\nencourages their use when `withMutations` will not suffice. Use caution to not\nreturn a mutable copy, which could result in undesired behavior.\n\n_Important!_: Only a select few methods can be used in `withMutations` including\n`set`, `push` and `pop`. These methods can be applied directly against a\npersistent data-structure where other methods like `map`, `filter`, `sort`,\nand `splice` will always return new immutable data-structures and never mutate\na mutable collection.\n\n## Lazy Seq\n\n`Seq` describes a lazy operation, allowing them to efficiently chain\nuse of all the higher-order collection methods (such as `map` and `filter`)\nby not creating intermediate collections.\n\n**Seq is immutable** — Once a Seq is created, it cannot be\nchanged, appended to, rearranged or otherwise modified. Instead, any mutative\nmethod called on a `Seq` will return a new `Seq`.\n\n**Seq is lazy** — `Seq` does as little work as necessary to respond to any\nmethod call. Values are often created during iteration, including implicit\niteration when reducing or converting to a concrete data structure such as\na `List` or JavaScript `Array`.\n\nFor example, the following performs no work, because the resulting\n`Seq`'s values are never iterated:\n\n```js\nimport { Seq } from 'immutable';\nconst oddSquares = Seq([1, 2, 3, 4, 5, 6, 7, 8])\n  .filter((x) =\u003e x % 2 !== 0)\n  .map((x) =\u003e x * x);\n```\n\nOnce the `Seq` is used, it performs only the work necessary. In this\nexample, no intermediate arrays are ever created, filter is called three\ntimes, and map is only called once:\n\n```js\noddSquares.get(1); // 9\n```\n\nAny collection can be converted to a lazy Seq with `Seq()`.\n\n```js\nimport { Map, Seq } from 'immutable';\nconst map = Map({ a: 1, b: 2, c: 3 });\nconst lazySeq = Seq(map);\n```\n\n`Seq` allows for the efficient chaining of operations, allowing for the\nexpression of logic that can otherwise be very tedious:\n\n```js\nlazySeq\n  .flip()\n  .map((key) =\u003e key.toUpperCase())\n  .flip();\n// Seq { A: 1, B: 2, C: 3 }\n```\n\nAs well as expressing logic that would otherwise seem memory or time\nlimited, for example `Range` is a special kind of Lazy sequence.\n\n```js\nimport { Range } from 'immutable';\nRange(1, Infinity)\n  .skip(1000)\n  .map((n) =\u003e -n)\n  .filter((n) =\u003e n % 2 === 0)\n  .take(2)\n  .reduce((r, n) =\u003e r * n, 1);\n// 1006008\n```\n\n## Comparison of filter(), groupBy(), and partition()\n\nThe `filter()`, `groupBy()`, and `partition()` methods are similar in that they\nall divide a collection into parts based on applying a function to each element.\nAll three call the predicate or grouping function once for each item in the\ninput collection. All three return zero or more collections of the same type as\ntheir input. The returned collections are always distinct from the input\n(according to `===`), even if the contents are identical.\n\nOf these methods, `filter()` is the only one that is lazy and the only one which\ndiscards items from the input collection. It is the simplest to use, and the\nfact that it returns exactly one collection makes it easy to combine with other\nmethods to form a pipeline of operations.\n\nThe `partition()` method is similar to an eager version of `filter()`, but it\nreturns two collections; the first contains the items that would have been\ndiscarded by `filter()`, and the second contains the items that would have been\nkept. It always returns an array of exactly two collections, which can make it\neasier to use than `groupBy()`. Compared to making two separate calls to\n`filter()`, `partition()` makes half as many calls it the predicate passed to\nit.\n\nThe `groupBy()` method is a more generalized version of `partition()` that can\ngroup by an arbitrary function rather than just a predicate. It returns a map\nwith zero or more entries, where the keys are the values returned by the\ngrouping function, and the values are nonempty collections of the corresponding\narguments. Although `groupBy()` is more powerful than `partition()`, it can be\nharder to use because it is not always possible predict in advance how many\nentries the returned map will have and what their keys will be.\n\n| Summary                       | `filter` | `partition` | `groupBy`      |\n| :---------------------------- | :------- | :---------- | :------------- |\n| ease of use                   | easiest  | moderate    | hardest        |\n| generality                    | least    | moderate    | most           |\n| laziness                      | lazy     | eager       | eager          |\n| # of returned sub-collections | 1        | 2           | 0 or more      |\n| sub-collections may be empty  | yes      | yes         | no             |\n| can discard items             | yes      | no          | no             |\n| wrapping container            | none     | array       | Map/OrderedMap |\n\n## Additional Tools and Resources\n\n- [Atom-store](https://github.com/jameshopkins/atom-store/)\n\n  - A Clojure-inspired atom implementation in Javascript with configurability\n    for external persistance.\n\n- [Chai Immutable](https://github.com/astorije/chai-immutable)\n\n  - If you are using the [Chai Assertion Library](https://chaijs.com/), this\n    provides a set of assertions to use against Immutable.js collections.\n\n- [Fantasy-land](https://github.com/fantasyland/fantasy-land)\n\n  - Specification for interoperability of common algebraic structures in JavaScript.\n\n- [Immutagen](https://github.com/pelotom/immutagen)\n\n  - A library for simulating immutable generators in JavaScript.\n\n- [Immutable-cursor](https://github.com/redbadger/immutable-cursor)\n\n  - Immutable cursors incorporating the Immutable.js interface over\n    Clojure-inspired atom.\n\n- [Immutable-ext](https://github.com/DrBoolean/immutable-ext)\n\n  - Fantasyland extensions for immutablejs\n\n- [Immutable-js-tools](https://github.com/madeinfree/immutable-js-tools)\n\n  - Util tools for immutable.js\n\n- [Immutable-Redux](https://github.com/gajus/redux-immutable)\n\n  - redux-immutable is used to create an equivalent function of Redux\n    combineReducers that works with Immutable.js state.\n\n- [Immutable-Treeutils](https://github.com/lukasbuenger/immutable-treeutils)\n\n  - Functional tree traversal helpers for ImmutableJS data structures.\n\n- [Irecord](https://github.com/ericelliott/irecord)\n\n  - An immutable store that exposes an RxJS observable. Great for React.\n\n- [Mudash](https://github.com/brianneisler/mudash)\n\n  - Lodash wrapper providing Immutable.JS support.\n\n- [React-Immutable-PropTypes](https://github.com/HurricaneJames/react-immutable-proptypes)\n\n  - PropType validators that work with Immutable.js.\n\n- [Redux-Immutablejs](https://github.com/indexiatech/redux-immutablejs)\n\n  - Redux Immutable facilities.\n\n- [Rxstate](https://github.com/yamalight/rxstate)\n\n  - Simple opinionated state management library based on RxJS and Immutable.js.\n\n- [Transit-Immutable-js](https://github.com/glenjamin/transit-immutable-js)\n  - Transit serialisation for Immutable.js.\n  - See also: [Transit-js](https://github.com/cognitect/transit-js)\n\nHave an additional tool designed to work with Immutable.js?\nSubmit a PR to add it to this list in alphabetical order.\n\n## Contributing\n\nUse [Github issues](https://github.com/immutable-js/immutable-js/issues) for requests.\n\nWe actively welcome pull requests, learn how to [contribute](https://github.com/immutable-js/immutable-js/blob/main/.github/CONTRIBUTING.md).\n\nImmutable.js is maintained within the [Contributor Covenant's Code of Conduct](https://www.contributor-covenant.org/version/2/0/code_of_conduct/).\n\n### Changelog\n\nChanges are tracked as [Github releases](https://github.com/immutable-js/immutable-js/releases).\n\n### License\n\nImmutable.js is [MIT-licensed](./LICENSE).\n\n### Thanks\n\n[Phil Bagwell](https://www.youtube.com/watch?v=K2NYwP90bNs), for his inspiration\nand research in persistent data structures.\n\n[Hugh Jackson](https://github.com/hughfdjackson/), for providing the npm package\nname. If you're looking for his unsupported package, see [this repository](https://github.com/hughfdjackson/immutable).\n","funding_links":["https://github.com/sponsors/jdeniau","https://github.com/sponsors/Methuselah96"],"categories":["Uncategorized","TypeScript","Libaries ##","基础","Frameworks/Libraries","JavaScript"],"sub_categories":["Uncategorized","源代码阅读","Coding Playgrounds","Parsers"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/facebook.github.io%2Fimmutable-js","html_url":"https://awesome.ecosyste.ms/projects/facebook.github.io%2Fimmutable-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/facebook.github.io%2Fimmutable-js/lists"}