网站首页 > 技术文章 正文
大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!
使用 Map 或 WeakMap 时,一个常见问题是:当不确定键是否已存在于 Map 中时应该如何处理更新操作。
通常的做法是先检查键是否存在,然后根据检查结果进行插入或更新操作,但这对开发者来说既不方便也并非最佳方案,因为需要在 Map 中进行多次查找,而这些查找原本可以在一次调用中完成。
最近 T39 提出了一个 proposal-upsert 提案,其建议添加一个 getOrInsert 和 getOrInsertComputed 方法,如果键已存在于 Map 或 WeakMap 中,则返回与键关联的值,否则插入键并返回该值。下面是该提案列出的一系列的用例:
1. 使用 getOrInsert 处理默认值
getOrInsert 可以简化默认值的处理,因为其不会覆盖现有值。比如下面的代码经常会出现在代码中:
// 目前使用方式
let prefs = new getUserPrefs();
if (!prefs.has("useDarkmode")) {
prefs.set("useDarkmode", true);
// default to true
}
有了 getOrInsert 后,使用起来就非常简单:
// 使用 getOrInsert 方法
let prefs = new getUserPrefs();
prefs.getOrInsert("useDarkmode", true);
// default to true
通过使用 getOrInsert,开发者可以在不同时间应用默认值,并确保后续的默认值不会覆盖先前值。例如:在存在用户偏好、操作系统偏好设置和应用程序默认值的情况下,可以使用 getOrInsert 依次设置,而无需担心相互覆盖。
2. 使用 getOrInsert 处理增量分组数据
getOrInsert 的一个典型用例是:当有新值可用时,根据键对数据进行分组。通过指定默认值,可以简化此操作,而无需在尝试更新之前检查键是否已存在于 Map 中。
// 现在代码
let grouped = new Map();
for (let [key, ...values] of data) {
if (grouped.has(key)) {
grouped.get(key).push(...values);
} else {
grouped.set(key, values);
}
}
有了 getOrInsert 后,一切将变得非常简单:
let grouped = new Map();
for (let [key, ...values] of data) {
grouped.getOrInsert(key, []).push(...values);
}
虽然 Map.groupBy 也能处理此类需求,但该方法要求在构建之前所有数据都已可用。而使用 getOrInsert 可以逐步构建和使用 Map,同时其还提供了处理对象以外的数据的灵活性。
const inventory = [
{name: "asparagus", type: "vegetables", quantity: 9},
{name: "bananas", type: "fruit", quantity: 5},
{name: "goat", type: "meat", quantity: 23},
{name: "cherries", type: "fruit", quantity: 12},
{name: "fish", type: "meat", quantity: 22},
];
const restock = {restock: true};
const sufficient = {restock: false};
const result = Map.groupBy(inventory, ({ quantity}) =>
quantity < 6 ? restock : sufficient,
);
console.log(result.get(restock));
// 输出 [{name: "bananas", type: "fruit", quantity: 5}]
3. 使用 getOrInsert 维护计数器
getOrInsert 的另一个常见用例是维护与特定键关联的计数器,其可以使代码更加简洁,并且这种先访问后修改的模式也更易于引擎优化。
例如当前的计数器示例:
let counts = new Map();
if (counts.has(key)) {
counts.set(key, counts.get(key) + 1);
} else {
counts.set(key, 1);
}
借助于 getOrInsert 方法,同样的逻辑将会简单的多:
let counts = new Map();
counts.set(key, counts.getOrInsert(key, 0) + 1);
4. 使用 getOrInsert 计算默认值
在某些场景下,确定默认值成本较高,此时可以使用 getOrInsertComputed 方法来达到该目的。
let grouped = new Map();
for (let [key, ...values] of data) {
grouped.getOrInsertComputed(key, () => []).push(...values);
}
5.getOrInsert 的 polyfill
目前 proposal-upsert 提案还处于 Stage 2.7 阶段,如果需要使用 getOrInsert 或者 getOrInsertComputed 方法,可以使用借助于下面的 polyfill:
// getOrInsert 的 polyfill
Map.prototype.getOrInsert = function (key, defaultValue) {
if (!this.has(key)) {
this.set(key, defaultValue);
}
return this.get(key);
};
// getOrInsertComputed 的 polyfill
Map.prototype.getOrInsertComputed = function (key, callbackFunction) {
if (!this.has(key)) {
this.set(key, callbackFunction(key));
}
return this.get(key);
};
参考资料
https://github.com/tc39/proposal-upsert
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/groupBy
https://hackr.io/blog/javascript-map
猜你喜欢
- 2025-05-15 宇宙厂:深入聊聊 CJS 和 ESM 模块化三点核心差异?
- 2025-05-15 #前端高手进阶#一起薅羊毛~
- 2025-05-15 前端基础进阶(十):深入详解函数的柯里化
- 2025-05-15 2025 年 Object 和 Map 如何选择?
- 2025-05-15 为何说 postMessage 才是真正的 setTimeout(0)?
- 2025-05-15 为什么高手写 JS 总是又快又好?这10个技巧你要知道
- 2025-05-15 2025 年 Deno 终于官宣 pnpm 和 Yarn 可使用 JSR?
- 2025-05-15 宇宙厂:为什么前端要了解 Interaction to Next Paint (INP)
- 2025-05-15 Node.js 原生支持 TypeScript?开发者需要了解的一切
- 2025-05-15 请务必用 postTask/isInputPending 释放JS主线程!
你 发表评论:
欢迎- 591℃几个Oracle空值处理函数 oracle处理null值的函数
- 584℃Oracle分析函数之Lag和Lead()使用
- 571℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 569℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 565℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 557℃【数据统计分析】详解Oracle分组函数之CUBE
- 542℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 537℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端react (48)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端路由 (61)
- 前端数组 (73)
- 前端js面试题 (50)
- 前端定时器 (59)
- 前端懒加载 (49)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle 中文 (51)
- oracle的函数 (57)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)