{"id":20903882,"url":"https://github.com/minjieliu/immot","last_synced_at":"2025-05-13T04:33:21.755Z","repository":{"id":44981664,"uuid":"443071943","full_name":"MinJieLiu/immot","owner":"MinJieLiu","description":"高性能操作不可变数据","archived":false,"fork":false,"pushed_at":"2022-09-26T08:27:46.000Z","size":459,"stargazers_count":32,"open_issues_count":1,"forks_count":3,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-04T15:53:07.158Z","etag":null,"topics":["immutable","javascript","react","typescript"],"latest_commit_sha":null,"homepage":"","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/MinJieLiu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-12-30T12:43:39.000Z","updated_at":"2025-04-07T17:36:17.000Z","dependencies_parsed_at":"2022-09-26T19:01:42.439Z","dependency_job_id":null,"html_url":"https://github.com/MinJieLiu/immot","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MinJieLiu%2Fimmot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MinJieLiu%2Fimmot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MinJieLiu%2Fimmot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MinJieLiu%2Fimmot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MinJieLiu","download_url":"https://codeload.github.com/MinJieLiu/immot/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253877265,"owners_count":21977632,"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":["immutable","javascript","react","typescript"],"created_at":"2024-11-18T13:15:17.929Z","updated_at":"2025-05-13T04:33:20.523Z","avatar_url":"https://github.com/MinJieLiu.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# immot\n\n[![NPM version][npm-image]][npm-url]\n[![Build status][build-image]][build-url]\n[![Test coverage][coveralls-image]][coveralls-url]\n[![Downloads][downloads-image]][downloads-url]\n[![Minified size][min-size-image]][bundlephobia-url]\n[![Gzip size][gzip-size-image]][bundlephobia-url]\n\n在不改变原始数据的情况下，创建新的拷贝。\n\n## 安装\n\n```bash\npnpm i immot\n```\n\n或者\n\n```bash\nyarn add immot\n```\n\n## 介绍\n\n`不可变数据` 是函数式编程中极其重要的一个基本概念。`React` 的 `state` 设计为只读，即 `不可变数据`，只能通过 `setState` 修改。此模块可以完美配合 `React`，以简化 `setState` 操作不可变数据的繁琐步骤。\n\n在 `React` 中，你不能这样做：\n\n```ts\nstate.a.b.c = 1;\n// or...\nstate.c.d.f.push(2);\n```\n\n通常，你会这样做：\n\n```ts\nconst nextState = {\n  ...state,\n  a: {\n    ...state.a,\n    b: {\n      ...state.a.b,\n      c: 1,\n    },\n  },\n};\n```\n\n现在有了 `immot`，让操作深层数据变得简单：\n\n```ts\nconst nextState = $setIn(state, ['a', 'b', 'c'], 1);\n\nnextState === state;\n// false\n```\n\n注意 **`immot` 不是深拷贝**，深拷贝操作极其昂贵，无法适用于日常开发。`immot` 只会创建改变的数据，会引用原对象中未改变的部分。\n\n`immot` 的 API 灵感来自于 `immutable-js`，但 `immutable-js` 有独立的结构模型，复杂度高。`immot` 的设计理念是要求简单、易用，不需要过多的心智负担。因此在设计之初就亲和原生的 `JSON` 结构，只提供辅助函数，大小 \u003c 1KB，就做到像 `immutable-js` 一样的效果。\n\n`immot` 做到了 `typescript` 类型安全。`$updateIn`、`$setIn`、`$mergeIn` 中的 `keyPath` 路径支持类型自动提示（目前只支持小于 7 层结构）。\n\n![code.gif](./bench/code.gif)\n\n## 使用\n\n```ts\nimport * as immot from 'immot';\n```\n\n或者只导入其中某个函数\n\n```ts\nimport { $updateIn } from 'immot';\n```\n\n`immot` 所有函数操作都会返回一个新的对象。\n\n### $set\n\n用于设置 `对象/数组/Map` 中的属性值。`keyPath` 为字符串。\n\n```ts\nconst result = immot.$set(demo, 'a', 1);\n```\n\n### $setIn\n\n用于设置 `对象/数组/Map` 中的属性值。它可以为深层对象做操作，`keyPath` 为路径数组\n\n```ts\nconst result = immot.$setIn(demo, ['a', 'b', 1, 'c'], 'good');\n```\n\n### $merge\n\n用于合并 `对象/数组` 中的属性列表。\n\n```ts\nconst result = immot.$merge(demo, { tom: 1, jack: 2 });\n\nconst result1 = immot.$merge(demo1, [5, 6]);\n```\n\n### $mergeIn\n\n用于合并 `对象/数组` 中的属性列表。它可以为深层对象做操作，`keyPath` 为路径数组\n\n```ts\nconst result = immot.$mergeIn(demo, ['a', 1, 'b'], { tom: 1, jack: 2 });\n```\n\n### $update\n\n通过回调函数设置 `对象/数组/Map` 中的属性值。`keyPath` 为字符串。\n\n```ts\nconst result = immot.$update(demo, 'money', (prev) =\u003e prev + 1);\n```\n\n### $updateIn\n\n通过回调函数设置 `对象/数组/Map` 中的属性值。它可以为深层对象做操作，`keyPath` 为路径数组\n\n```ts\nconst result = immot.$updateIn(demo, ['todoList', 0, 'complete'], (complete) =\u003e !complete);\n```\n\n### $delete\n\n用于删除 `对象/数组/Map` 中的可选属性值，`keyPath` 为字符串或者数组\n\n```ts\nconst result = immot.$delete(demo, 'a1');\nconst result1 = immot.$delete(demo, ['a1', 'a2']);\n```\n\n### $push\n\n类似 `Array.prototype.push`，但返回新数组\n\n```ts\nconst result = immot.$push(demo, 4);\n```\n\n### $pop\n\n类似 `Array.prototype.pop`，但返回新数组\n\n```ts\nconst result = immot.$pop(demo);\n```\n\n### $shift\n\n类似 `Array.prototype.shift`，但返回新数组\n\n```ts\nconst result = immot.$shift(demo);\n```\n\n### $unshift\n\n类似 `Array.prototype.unshift`，但返回新数组\n\n```ts\nconst result = immot.$unshift(demo, 4);\n```\n\n### $splice\n\n类似 `Array.prototype.splice`，但返回新数组\n\n```ts\nconst result = immot.$splice(demo, 1, 0, 'test');\n```\n\n### 性能测试\n\n在 `/bench` 目录中有性能测试对比的样例，可以 clone 本项目测试\n\n```bash\ncd bench\npnpm i\nnode index.mjs\n```\n\n注意：\n\n1. 数值为每秒操作数量，越高越好\n2. 样例中 `immer` 关闭了自动冻结对象的特性，否则结果会更差。\n3. 数组性能测试图中隐藏了 `immutableJS` 数据，用空间换取时间的方式导致数值太高，影响对比。\n\n在 Node v14.17.0 的测试结果：\n\n常规数据和深层数据\n![Performance](./bench/Performance.png)\n\n50000 长度的数组\n![Performance1](./bench/Performance1.png)\n\n[npm-image]: https://img.shields.io/npm/v/immot.svg?style=flat-square\n[npm-url]: https://npmjs.org/package/immot\n[build-image]: https://github.com/MinJieLiu/immot/actions/workflows/node.js.yml/badge.svg\n[build-url]: https://github.com/MinJieLiu/immot/actions\n[coveralls-image]: https://img.shields.io/coveralls/MinJieLiu/immot.svg?style=flat-square\n[coveralls-url]: https://coveralls.io/r/MinJieLiu/immot\n[downloads-image]: http://img.shields.io/npm/dm/immot.svg?style=flat-square\n[downloads-url]: https://npmjs.org/package/immot\n[min-size-image]: https://badgen.net/bundlephobia/min/immot?label=minified\n[gzip-size-image]: https://badgen.net/bundlephobia/minzip/immot?label=gzip\n[bundlephobia-url]: https://bundlephobia.com/result?p=immot\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminjieliu%2Fimmot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fminjieliu%2Fimmot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminjieliu%2Fimmot/lists"}