JavaScript Map扩展:实现对象键值化与生成器惰性迭代优化

JavaScript Map扩展:实现对象键值化与生成器惰性迭代优化

本文探讨了如何通过扩展JavaScript的Map类,实现基于对象内容(而非引用)的键存储与检索。通过重写set和get方法,利用JSON.stringify将对象键序列化,解决了Map默认按引用比较键的问题。同时,文章详细介绍了如何优化keys()等生成器方法,避免一次性加载所有键,从而保持迭代器的惰性特性,提高性能和内存效率。

理解JavaScript Map的对象键行为

javascript的map对象在处理键时,默认采用严格相等(===)进行比较。这意味着当使用对象作为键时,map会基于对象的内存引用进行比较,而非其内部属性或值。这在某些场景下可能会导致非预期的行为。

例如,以下代码演示了Map的默认行为:

let newMap = new Map();const obj1 = {'a': 1, 'b' :2};newMap.set(obj1, 123);const copyObj1 = {...obj1}; // 创建了一个内容相同但引用不同的新对象console.log(newMap.get(obj1));      // 输出: 123 (因为引用相同)console.log(newMap.get(copyObj1));   // 输出: undefined (因为引用不同)

为了实现newMap.get(copyObj1)也能返回123,我们需要一种机制,让Map能够基于对象的内容进行键的比较和查找。

扩展Map实现基于值的对象键

要解决Map基于引用比较对象键的问题,一个常见的策略是在内部将对象键序列化为字符串。这样,即使是内容相同的不同引用对象,只要其序列化后的字符串相同,就能被视为同一个键。我们可以通过扩展Map类来实现这一点。

interface ISquareCoordinate {    x: number;    y: number;}class CoordMapper extends Map<string, Array> {    /**     * 重写set方法,将对象键序列化为字符串     * @param k 作为键的对象     * @param v 对应的值     * @returns 当前Map实例     */    set(k: ISquareCoordinate, v: Array): this {        const stringifiedKey = JSON.stringify(k);        return super.set(stringifiedKey, v);    }    /**     * 重写get方法,将对象键序列化后进行查找     * @param k 作为键的对象     * @returns 对应的值,如果不存在则返回undefined     */    get(k: ISquareCoordinate): Array | undefined {        const stringifiedKey = JSON.stringify(k);        return super.get(stringifiedKey);    }    /**     * 重写has方法,支持基于对象内容的键检查     * @param k 作为键的对象     * @returns 如果Map中存在该键,则返回true,否则返回false     */    has(k: ISquareCoordinate): boolean {        const stringifiedKey = JSON.stringify(k);        return super.has(stringifiedKey);    }    /**     * 重写delete方法,支持基于对象内容的键删除     * @param k 作为键的对象     * @returns 如果成功删除,则返回true,否则返回false     */    delete(k: ISquareCoordinate): boolean {        const stringifiedKey = JSON.stringify(k);        return super.delete(stringifiedKey);    }}

在上述CoordMapper类中,我们重写了set、get、has和delete方法。在这些方法内部,传入的对象键k首先通过JSON.stringify(k)转换为字符串,然后将这个字符串作为实际的键传递给父类Map的对应方法。这样,无论传入的是原始对象还是其内容相同的副本,只要JSON.stringify的结果一致,Map就能正确地处理它们。

立即学习“Java免费学习笔记(深入)”;

优化生成器方法:保持惰性迭代

Map类提供了keys()、values()和entries()等生成器方法,它们返回迭代器,允许我们惰性地遍历集合中的元素。然而,在扩展类中重写这些方法时,需要注意保持其惰性特性,避免一次性加载所有数据到内存中。

考虑一个不优化的keys()实现:

// 不推荐的实现方式:一次性加载所有键* keys(): Generator {   const keysArr = [...super.keys()]; // 将所有键加载到数组中   for (const key of keysArr){      yield JSON.parse(key); // 然后逐个解析并yield   }}

这种实现方式的问题在于[…super.keys()]会立即迭代父类Map的所有键并将其收集到一个数组中。如果Map中包含大量键,这会导致显著的内存开销和性能下降,失去了生成器应有的惰性优势。

正确的优化方法是直接迭代父类生成器返回的迭代器,并逐个处理:

class CoordMapper extends Map<string, Array> {    // ... (set, get, has, delete 方法如上)    /**     * 优化后的keys()生成器方法,保持惰性迭代     * @returns 一个生成器,每次yield一个解析后的对象键     */    * keys(): Generator {        const parentKeyIterator = super.keys(); // 获取父类的键迭代器        for (const key of parentKeyIterator) {            yield JSON.parse(key); // 逐个解析并yield        }    }    /**     * 优化后的values()生成器方法 (示例,实际根据需求实现)     * @returns 一个生成器,每次yield一个值     */    * values(): Generator<Array, void, unknown> {        const parentValueIterator = super.values();        for (const value of parentValueIterator) {            yield value; // 值通常不需要额外处理        }    }    /**     * 优化后的entries()生成器方法 (示例,实际根据需求实现)     * @returns 一个生成器,每次yield一个 [解析后的键, 值] 对     */    * entries(): Generator<[ISquareCoordinate, Array], void, unknown> {        const parentEntryIterator = super.entries();        for (const [stringifiedKey, value] of parentEntryIterator) {            yield [JSON.parse(stringifiedKey), value];        }    }}

通过直接迭代super.keys()返回的parentKeyIterator,我们确保了keys()生成器在每次调用next()时,才会向父类迭代器请求下一个键,然后进行JSON.parse并yield。这种方式完美地保留了生成器的惰性特性,避免了不必要的内存消耗。values()和entries()方法也可以采用类似的模式进行优化。

注意事项与最佳实践

JSON.stringify的局限性:

JSON.stringify不能处理循环引用,会导致报错。它会忽略函数、undefined、Symbol和BigInt类型的值。对于对象键的顺序敏感:{a:1, b:2}和{b:2, a:1}在JSON.stringify后可能得到不同的字符串,除非属性键是简单的数字或字符串且顺序固定。对于简单的坐标对象等,这通常不是问题。如果需要处理更复杂的对象作为键,可能需要实现自定义的序列化逻辑,或者使用第三方库。

性能开销: 频繁地进行JSON.stringify和JSON.parse操作会带来一定的性能开销。对于键操作非常频繁且性能要求极高的场景,需要权衡这种便利性与性能损耗。

类型安全: 在TypeScript环境中,为扩展类及其方法定义准确的类型签名至关重要,如示例中所示,确保代码的健壮性和可维护性。

键的不可变性: 理想情况下,作为键的对象应该是不可变的。如果键对象在存储后被修改,其序列化后的字符串可能会发生变化,导致后续的get或has操作失败,因为它们会尝试查找基于新序列化字符串的键。

总结

通过扩展Map类并重写其核心方法,我们可以有效地实现基于对象内容而非引用的键存储机制,极大地增强了Map在特定场景下的灵活性。同时,在重写keys()、values()和entries()等生成器方法时,务必注意保持其惰性迭代的特性,避免不必要的性能和内存开销。理解JSON.stringify的优缺点及其对键对象的要求,有助于构建更健壮和高效的数据结构。

以上就是JavaScript Map扩展:实现对象键值化与生成器惰性迭代优化的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1520071.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月20日 12:59:46
下一篇 2025年12月20日 12:59:56

相关推荐

  • TypeScript 中如何约束对象为 CSS 属性?

    typescript 中如何约束对象为 css 属性 想要约束一个对象为 css 属性,以便在调用函数时得到自动补全提示,可以采用以下方法: 使用 react 的 cssproperties 类型 对于 react 项目,可以使用 react 提供的 cssproperties 类型: 立即学习“前…

    2025年12月24日
    300
  • 如何在 TypeScript 中约束对象为 CSS 属性?

    如何在 typescript 中约束对象为 css 属性? 在 typescript 中,为特定目的而约束对象类型是很重要的。在本文中,我们将探究如何将对象约束为包含 css 属性。 考虑以下函数: function setattrstoelement(el: htmlelement, attr: …

    2025年12月24日
    000
  • 如何使用 TypeScript 约束对象以匹配 CSS 属性?

    如何约束 typescript 对象以匹配 css 属性? setattrstoelement 函数接收两个参数,其中第二个参数应为 css 属性。对于 react 项目,可以使用 cssproperties 类型: import { cssproperties } from “react”;fun…

    2025年12月24日
    000
  • 为什么使用 :global 修改 Antd 样式无效?

    :global 修改 antd 样式为何无效 本文旨在帮助您解决在组件内使用:global修改 antd 全局样式未生效的问题。 问题描述 您在组件内使用:global修改 antd 按钮样式,但没有生效。完整代码可参考 https://codesandbox.io/s/fk7jnl 。 解决方案 …

    2025年12月24日
    000
  • 为什么在 React 组件中无法获得 Tailwind CSS 语法提示?

    为什么在 React 组件中无法获得 Tailwind CSS 语法提示? 你在 VSCode 中编写 HTML 文件时,可以正常获取 Tailwind CSS 语法提示。但当你尝试在 React 组件中编写 Tailwind CSS 时,这些提示却消失不见了。这是什么原因造成的? 解决方案 要解决…

    2025年12月24日
    000
  • 如何在 VSCode 中为 React 组件启用 Tailwind CSS 提示?

    在 vscode 中为 react 组件启用 tailwind css 提示 如果你在使用 vscode 编写 react 组件时,发现 tailwind css 提示无法正常显示,这里有一个解决方法: 安装 tailwind css intellisense 插件 这是实现代码提示的关键,确保你已…

    2025年12月24日
    200
  • CSS 砌体 Catness

    css 就像技术中的其他东西一样 – 它总是在变化和发展。该领域正在进行的开发是 css 网格布局模块级别 3,也称为 css masonry 布局。 theo 制作了一段视频,介绍了它的开发方式以及苹果和谷歌就如何实施它进行的辩论。 所有这些让我很高兴尝试 css 砌体! webkit…

    好文分享 2025年12月24日
    000
  • 深入理解CSS框架与JS之间的关系

    深入理解CSS框架与JS之间的关系 在现代web开发中,CSS框架和JavaScript (JS) 是两个常用的工具。CSS框架通过提供一系列样式和布局选项,可以帮助我们快速构建美观的网页。而JS则提供了一套功能强大的脚本语言,可以为网页添加交互和动态效果。本文将深入探讨CSS框架和JS之间的关系,…

    2025年12月24日
    000
  • 项目实践:如何结合CSS和JavaScript打造优秀网页的经验总结

    项目实践:如何结合CSS和JavaScript打造优秀网页的经验总结 随着互联网的快速发展,网页设计已经成为了各行各业都离不开的一项技能。优秀的网页设计可以给用户留下深刻的印象,提升用户体验,增加用户的黏性和转化率。而要做出优秀的网页设计,除了对美学的理解和创意的运用外,还需要掌握一些基本的技能,如…

    2025年12月24日
    200
  • 学完HTML和CSS之后我应该做什么?

    网页开发是一段漫长的旅程,但是掌握了HTML和CSS技能意味着你已经赢得了一半的战斗。这两种语言对于学习网页开发技能来说非常重要和基础。现在不可或缺的是下一个问题,学完HTML和CSS之后我该做什么呢? 对这些问题的答案可以分为2-3个部分,你可以继续练习你的HTML和CSS编码,然后了解在学习完H…

    2025年12月24日
    000
  • 聊聊怎么利用CSS实现波浪进度条效果

    本篇文章给大家分享css 高阶技巧,介绍一下如何使用css实现波浪进度条效果,希望对大家有所帮助! 本文是 CSS Houdini 之 CSS Painting API 系列第三篇。 现代 CSS 之高阶图片渐隐消失术现代 CSS 高阶技巧,像 Canvas 一样自由绘图构建样式! 在上两篇中,我们…

    2025年12月24日 好文分享
    200
  • 巧用距离、角度及光影制作炫酷的 3D 文字特效

    如何利用 css 实现3d立体的数字?下面本篇文章就带大家巧用视觉障眼法,构建不一样的 3d 文字特效,希望对大家有所帮助! 最近群里有这样一个有意思的问题,大家在讨论,使用 CSS 3D 能否实现如下所示的效果: 这里的核心难点在于,如何利用 CSS 实现一个立体的数字?CSS 能做到吗? 不是特…

    2025年12月24日 好文分享
    000
  • CSS高阶技巧:实现图片渐隐消的多种方法

    将专注于实现复杂布局,兼容设备差异,制作酷炫动画,制作复杂交互,提升可访问性及构建奇思妙想效果等方面的内容。 在兼顾基础概述的同时,注重对技巧的挖掘,结合实际进行运用,欢迎大家关注。 正文从这里开始。 在过往,我们想要实现一个图片的渐隐消失。最常见的莫过于整体透明度的变化,像是这样: 立即学习“前端…

    2025年12月24日 好文分享
    000
  • css实现登录按钮炫酷效果(附代码实例)

    今天在网上看到一个炫酷的登录按钮效果;初看时感觉好牛掰;但是一点一点的抛开以后发现,并没有那么难;我会将全部代码贴出来;如果有不对的地方,大家指点一哈。 分析 我们抛开before不谈的话;其实原理和就是通过背景大小以及配合位置达到颜色渐变的效果。 text-transform: uppercase…

    2025年12月24日
    000
  • CSS flex布局属性:align-items和align-content的区别

    在用flex布局时,发现有两个属性功能好像有点类似:align-items和align-content,乍看之下,它们都是用于定义flex容器中元素在交叉轴(主轴为flex-deriction定义的方向,默认为row,那么交叉轴跟主轴垂直即为column,反之它们互调,flex基本的概念如下图所示)…

    2025年12月24日 好文分享
    000
  • 手把手教你用 transition 实现短视频 APP的点赞动画

    怎么使用纯 css 实现有趣的点赞动画?下面本篇文章就带大家了解一下巧妙借助 transition实现点赞动画的方法,希望对大家有所帮助! 在各种短视频界面上,我们经常会看到类似这样的点赞动画: 非常的有意思,有意思的交互会让用户更愿意进行互动。 那么,这么有趣的点赞动画,有没有可能使用纯 CSS …

    2025年12月24日 好文分享
    000
  • 巧用CSS实现各种奇形怪状按钮(附代码)

    本篇文章带大家看看怎么使用 CSS 轻松实现高频出现的各类奇形怪状按钮,希望对大家有所帮助! 怎么样使用 CSS 实现一个内切角按钮呢、怎么样实现一个带箭头的按钮呢? 本文基于一些高频出现在设计稿中的,使用 css 实现稍微有点难度和技巧性的按钮,讲解使用 css 如何尽可能的实现它们。【推荐学习:…

    2025年12月24日 好文分享
    000
  • 原来利用纯CSS也能实现文字轮播与图片轮播!

    怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯css也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助! 今天,分享一个实际业务中能够用得上的动画技巧。【推荐学习:css视频教程】 巧用逐帧动画,配合补间动画实现一个无限循环的轮播效果,像是这样: 立即学习“前端…

    2025年12月24日 好文分享
    000
  • HTML+CSS+JS实现雪花飘扬(代码分享)

    使用html+css+js如何实现下雪特效?下面本篇文章给大家分享一个html+css+js实现雪花飘扬的示例,希望对大家有所帮助。 很多南方的小伙伴可能没怎么见过或者从来没见过下雪,今天我给大家带来一个小Demo,模拟了下雪场景,首先让我们看一下运行效果 可以点击看看在线运行:http://hai…

    2025年12月24日 好文分享
    500
  • 总结整理:需要避坑的五大常见css错误(收藏)

    本篇文章给大家总结5个最常见的css错误,并介绍一下避坑方法,希望对大家有所帮助! 正如我们今天所知,CSS语言是web的一个重要组成部分。它使我们有能力绘制元素在屏幕、网页或其他媒体中的展示方式。 它简单、强大,而且是声明式的。我们可以很容易地实现复杂的事情,如暗黑/光明模式。然而,对它有很多误解…

    2025年12月24日
    000

发表回复

登录后才能评论
关注微信