新闻中心

优化 J*aScript 类中缓存属性处理的技巧

2025-10-28
浏览次数:
返回列表

 优化 JavaScript 类中缓存属性处理的技巧

本文旨在提供一种更简洁高效的方法来处理 j*ascript 类中的缓存属性,避免冗余的重复代码。通过使用装饰器函数和空值合并赋值运算符(??=),我们可以显著简化缓存逻辑,提高代码的可读性和可维护性。文章将提供详细的代码示例和解释,帮助开发者理解和应用这种优化方案。

在 J*aScript 类中,为了避免重复计算,经常需要对方法的返回值进行缓存。一种常见的做法是在方法内部检查缓存变量是否存在,如果不存在则进行计算并缓存,然后返回缓存的值。然而,当类中存在大量需要缓存的方法时,这种方式会导致大量的重复代码,降低代码的可读性和维护性。本文将介绍一种更优雅的解决方案,通过使用装饰器函数和空值合并赋值运算符(`??=`),可以显著简化缓存逻辑。 ### 使用装饰器函数实现缓存 装饰器函数是一种可以修改或增强函数行为的模式。我们可以创建一个装饰器函数,专门用于处理缓存逻辑,然后将其应用到需要缓存的方法上。 以下是一个名为 `enableCache` 的装饰器函数的示例: ```j*ascript function enableCache(func) { const cache = {}; return function(...args) { const key = JSON.stringify([this, ...args]); return (cache[key] ??= { value: func.apply(this, args) }).value; }; }

这个 enableCache 函数接受一个函数 func 作为参数,并返回一个新的函数。当调用返回的新函数时,它首先检查缓存 cache 中是否存在对应于当前 this 和 args 的缓存值。如果缓存不存在,则调用原始函数 func 计算结果,并将结果存储在缓存中,然后返回缓存的值。

代码解释:

Yes!SUN企业网站系统 3.5 Build 20100303 Yes!SUN企业网站系统 3.5 Build 20100303

Yes!Sun基于PHP+MYSQL技术,体积小巧、应用灵活、功能强大,是一款为企业网站量身打造的WEB系统。其创新的设计理念,为企业网的开发设计及使用带来了全新的体验:支持前沿技术:动态缓存、伪静态、静态生成、友好URL、SEO设置等提升网站性能、用户体验、搜索引擎友好度的技术均为Yes!Sun所支持。易于二次开发:采用独创的平台化理念,按需定制项目中的各种元素,如:产品属性、产品相册、新闻列表

Yes!SUN企业网站系统 3.5 Build 20100303 0 查看详情 Yes!SUN企业网站系统 3.5 Build 20100303
  • const cache = {};: 定义一个 cache 对象,用于存储缓存的结果。 键值对的键是函数调用参数的 JSON 字符串,值是包含 value 属性的对象,value 属性存储函数的返回值。
  • return function(...args) { ... }: 返回一个闭包,这个闭包是实际被调用的函数。它接收任意数量的参数 ...args。
  • const key = JSON.stringify([this, ...args]);: 创建一个缓存键。 使用 JSON.stringify 将 this (函数执行上下文) 和所有参数转换为字符串,以便用作 cache 对象的键。
  • (cache[key] ??= { value: func.apply(this, args) }).value;: 这是缓存的核心逻辑。
    • cache[key] ??= { value: func.apply(this, args) }: 使用空值合并赋值运算符 ??=。如果 cache[key] 的值为 null 或 undefined,则将 { value: func.apply(this, args) } 赋值给 cache[key]。 func.apply(this, args) 调用原始函数 func,并传入正确的 this 上下文和参数。
    • .value: 访问缓存对象的 value 属性,即函数的返回值。

应用装饰器函数到类的方法

为了方便地将 enableCache 装饰器函数应用到类的多个方法上,我们可以创建一个名为 enableCacheOnMethods 的辅助函数:

function enableCacheOnMethods(cls) {
    const obj = cls.prototype;
    for (const method of Object.getOwnPropertyNames(obj)) {
        if (typeof obj[method] === "function" && method !== "constructor") {
            obj[method] = enableCache(obj[method]);
        }
    }
}

这个 enableCacheOnMethods 函数接受一个类 cls 作为参数,然后遍历该类的原型对象上的所有方法。对于每个方法,它都会调用 enableCache 函数来包装该方法,从而实现缓存功能。

代码解释:

  • const obj = cls.prototype;: 获取类的原型对象。类的所有方法都定义在原型对象上。
  • for (const method of Object.getOwnPropertyNames(obj)) { ... }: 遍历原型对象的所有属性名。 Object.getOwnPropertyNames 返回一个数组,包含原型对象的所有属性名,包括不可枚举的属性。
  • if (typeof obj[method] === "function" && method !== "constructor") { ... }: 检查当前属性是否是一个函数,并且不是构造函数。 我们只需要缓存普通的方法,而不需要缓存构造函数。
  • obj[method] = enableCache(obj[method]);: 使用 enableCache 装饰器函数包装当前方法,并将包装后的函数重新赋值给原型对象上的同名属性。

示例

以下是一个使用 enableCache 和 enableCacheOnMethods 函数的完整示例:

class myClass {
    divisors(n) {
        console.log(`executing divisors(${n})`);
        const arr = [];
        for (let i = 2; i <= n; i++) {
            if (n % i == 0) arr.push(i);
        }
        return arr;
    }
    factorial(n) {
        console.log(`executing factorial(${n})`);
        let res = 1;
        while (n > 1) res *= n--;
        return res;
    }
}

enableCacheOnMethods(myClass);

let obj = new myClass;
console.log(...obj.divisors(15));
console.log(...obj.divisors(48));
console.log(obj.factorial(10));
console.log(...obj.divisors(15)); // 使用缓存
console.log(obj.factorial(10)); // 使用缓存

在这个示例中,divisors 和 factorial 方法都会被缓存。当第一次调用这些方法时,会执行实际的计算,并将结果存储在缓存中。后续对相同参数的调用将直接从缓存中返回结果,而不会再次执行计算。

注意事项

  • 缓存键的生成方式需要仔细考虑,确保能够唯一标识不同的函数调用。在上面的示例中,我们使用 JSON.stringify([this, ...args]) 来生成缓存键。对于包含循环引用的对象,这种方式可能会导致错误。
  • 缓存的大小需要进行控制,避免占用过多的内存。可以考虑使用 LRU (Least Recently Used) 等缓存淘汰算法。
  • 装饰器函数会修改类的原型对象,可能会影响到其他使用该类的代码。

总结

通过使用装饰器函数和空值合并赋值运算符,我们可以显著简化 J*aScript 类中缓存属性的处理逻辑。这种方法不仅可以减少重复代码,提高代码的可读性和维护性,还可以提高代码的性能。在实际开发中,可以根据具体的需求选择合适的缓存策略和缓存键生成方式。

以上就是优化 J*aScript 类中缓存属性处理的技巧的详细内容,更多请关注其它相关文章!


# 键值  # 游戏营销推广  # 软件推广营销价格计算方法  # 隆昌网站推广费用是多少  # seo是啥东西  # 餐饮网站建设价钱  # 西湖区网站推广哪里好  # 易推网站建设  # 鹤岗网站开发建设  # 日用品推广网站排名大全  # 北碚网站推广口碑公司  # 返回值  # 遍历  # javascript  # 创建一个  # 并将  # 是一个  # 我们可以  # 企业网站  # 类中  # 运算符  # 键值对  # app  # json  # js  # java 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: Win11怎么合并任务栏图标 Win11开启任务栏合并减少图标占空间【方法】  Fabric Mod开发:在1.19.3+版本中正确添加自定义物品并管理物品组  Python字典中优雅地迭代剩余元素的方法  Win11怎么用U盘重装系统 Win11制作启动盘并重装系统完整教程【详解】  Flexbox布局实践:实现粘性导航栏与底部固定页脚  Discord Slash 命令响应超时问题的异步解决方案  初次安装JDK时环境变量如何正确配置_J*A_HOME与PATH设置规则讲解  Lar*el 递归关系中排除指定分支的教程  为什么简单的XML文件也会解析失败? 检查隐藏的非打印字符(如BOM)的方法  Odoo 16:在表单视图中基于当前记录动态修改Tree视图属性  抖音隐秘迷城小游戏入口_ 抖音冒险解谜小游戏秒玩  uc浏览器网页版入口 uc浏览器网页版最新网址  在python-socketio事件处理器中安全访问Flask应用上下文  在React函数组件中利用原生HTML5进行邮箱地址验证  QQ邮箱电脑版登录入口_QQ邮箱官方网站登录平台  夸克浏览器桌面版同步不了书签怎么处理 夸克浏览器跨设备同步异常解决方案  AO3镜像入口大全 AO3网页版内容访问全集  在命令行怎么运行html项目_命令行运行html项目方法【教程】  德邦快递查询平台 德邦快递物流信息查询入口  谷歌邮箱注册显示错误Gmail服务器异常与延迟处理  Golang如何使用new_Go new分配内存机制讲解  提升屏幕阅读器对“m”时间单位的播报准确性:HTML与CSS组合解决方案  正确连接J*aScript到HTML实现可点击图片与自定义事件处理  Win11怎么隐藏桌面图标 Win11一键隐藏所有桌面元素及恢复显示  composer的"require-dev"部分是用来做什么的?  Golang如何通过reflect操作map_Golang reflect map操作与遍历技巧  Mac怎么锁定备忘录_Mac备忘录加密设置教程  蛙漫正版漫画平台入口_蛙漫免费阅读全站漫画资源  C#如何安全地从用户上传的XML文件中读取数据? 验证与清理策略  知音漫客正版漫画平台_知音漫客官网账号登录  拷贝漫画电脑版官网入口 拷贝漫画(PC版)在线直达  探索高级语言到原生C/C++的转译:挑战与内存管理策略  Win10系统怎么查看已安装更新_Win10卸载有问题的更新补丁  从J*aScript对象中精确提取指定属性的教程  微信怎么把收藏的内容分类管理 微信收藏内容标签分类方法  MongoDB Aggregation:在嵌套对象数组中精确匹配ObjectId  中兴Axon42Ultra怎样在文件App筛图_iPhone中兴Axon42Ultra文件App筛图【图片筛选】  小红书网页版入口链接分享 小红书官网直接进  京东单号查询入口_京东快递订单追踪入口  谷歌浏览器浏览体验优化_谷歌浏览器新版直连永久可用提示  海量存储:机器视觉智能化的核心基石  MongoDB聚合管道:正确匹配对象数组中_id的方法  天眼查企业查询官网入口 天眼查官方网页版查询  厨房不锈钢水槽发黑生锈怎么处理_水槽用可乐+锡纸2分钟抛亮如新  Golang如何使用bytes.Split分割字节切片_Golang bytes切片分割方法  想当下一个《2077》?《心之眼》Steam评价升至"多半好评"  抖音创作助手登录入口_抖音创作辅助工具官网直达  必由学官网快捷入口 必由学网页版在线学习平台  《GTA6》开发画面疑似泄露!这次可不是AI了  126邮箱网页版官方入口 126邮箱账号在线登录平台 

搜索