【前端学习——js篇】7.函数缓存

具体见:https://github.com/febobo/web-interview

7.函数缓存

函数缓存,就是将函数运算过的结果进行缓存

本质上就是用空间(缓存存储)换时间(计算过程)

常用于缓存数据计算结果和缓存对象。

其实现主要通过闭包、柯里化和高阶函数。

下面主要介绍下柯里化:

①柯里化

柯里化(currying)是一种函数式编程的概念,指的是将一个带有多个参数的函数转换成一系列只接受一个参数的函数的过程。这些接受单一函数的函数可以依次调用,每次调用都会返回一个新的函数,直到所有参数收集完毕,最好返回最终的结果。


具体例子

//柯里化
// 原始的加法函数
function add(x, y) {return x + y;
}// 柯里化后的加法函数
function curriedAdd(x) {return function(y) {return x + y;};
}// 使用柯里化后的函数
const add5 = curriedAdd(5);
console.log(add5(3)); // 输出: 8const add7 = curriedAdd(7);
console.log(add7(3)); // 输出: 10

在上面的示例中,add 是一个接受两个参数的加法函数。通过柯里化,我们定义了一个 curriedAdd 函数,它接受一个参数 x,并返回一个函数,这个返回的函数接受参数 y,并返回 x + y 的结果。通过这种方式,我们可以先传递一个参数 x,然后再传递另一个参数 y,实现了对多参数函数的拆分调用。

通过柯里化,我们可以将一个接受多个参数的函数转换为一个接受单个参数的函数链。这种技术有助于简化函数的调用方式,提高函数的灵活性和复用性。

②高阶函数

高阶函数(Higher-Order Functions)是指接受一个或多个函数作为参数,返回一个函数的函数。换句话说,高阶函数要么接受一个或多个函数作为参数,要么返回一个函数,或者同时具备这两个特点。

在js 中,函数被视为一等公民,因此可以像其他值一样被传递和操作。这种特性使得函数可以作为参数传递给其他函数,也可以作为其他函数的返回值。


具体例子

// 高阶函数示例:接受一个函数作为参数
function operate(func, x, y) {return func(x, y);
}function add(a, b) {return a + b;
}function multiply(a, b) {return a * b;
}console.log(operate(add, 3, 4)); // 输出: 7
console.log(operate(multiply, 3, 4)); // 输出: 12// 高阶函数示例:返回一个函数
function createMultiplier(multiplier) {return function(x) {return x * multiplier;};
}const double = createMultiplier(2);
console.log(double(5)); // 输出: 10

在上面的示例中,operate 是一个接受一个函数作为参数的高阶函数,它可以根据传入的函数不同来执行不同的操作。另外,createMultiplier 是一个返回函数的高阶函数,它返回一个乘法函数,用于计算传入值的倍数。

③函数缓存

实现原理也很简单,把参数和对应的结果数据存在一个对象中,调用时判断参数对应的数据是否存在,存在就返回对应的结果数据,否则就返回计算结果。


const memoize = function (func, content) {let cache = Object.create(null)content = content || this //函数被定义时的上下文return (...key) => {console.log(cache);if (!cache[key]) {cache[key] = func.apply(content, key)}return cache[key]}}function add(a,b){return a + b;
}const calc = memoize(add);
const num1 = calc(100,200);
//输出cache可以看到:[Object: null prototype] { '100,200': 300}
const num2 = calc(100,200); //直接从缓存得到结果
const num3 = calc(1000,2000);
console.log(num2); 

过程分析:

  • 在当前函数作用域定义了一个空对象,用于缓存运行结果
  • 运用柯里化返回一个函数,返回的函数因为作用域链的原因,可以访问到cache
  • 然后判断输入参数是不是在cache的中。如果已经存在,直接返回cache的内容,如果没有存在,使用函数func对输入参数求值,然后把结果存储在cache中。
④应用场景

虽然使用缓存效率是非常高的,但并不是所有场景都适用,因此千万不要极端的将所有函数都添加缓存

以下几种情况下,适合使用缓存:

  • 对于昂贵的函数调用,执行复杂计算的函数
  • 对于具有有限且高度重复输入范围的函数
  • 对于具有重复输入值的递归函数
  • 对于纯函数,即每次使用特定输入调用时返回相同输出的函数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/773225.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Code Review(代码审查)

代码审查是软件开发生命周期的重要组成部分。它能显著提高开发人员的代码质量。 这个过程就像写一本书。作者写好了内容,出版社编辑对其进行了校审,所以没有出现任何错误,例如将“你”与“你的”混淆。这个案例中,代码审查是阅读…

Linux reboot命令教程:如何安全地重启你的Linux系统(附实例详解和注意事项)

Linux reboot命令介绍 reboot命令用于重新启动你的Linux系统。当你的系统内核更新时,除非你正在使用Livepatch或KernelCare,否则你需要重启你的Linux系统。在其他情况下,例如解决硬件问题、安装应用程序等,也可能需要重新启动系统…

我的创作纪念日 ---- 2024/3/26

前言 2024.3.26是我在CSDN成为创作者的第128天,也是我第一次真正在网上创作的第128天 当我还在日常创作时,突然发现我收到了一封信 我想我可以分享一下这段时间的感想以及收获 机缘 在CSDN的这段时间里,我学习到了很多知识,也…

数据结构——链表(单链表)

大家好,又是我(小锋),今天给大家带了一个比较有挑战的章节(链表),但是不用担心,小锋会陪大家一起度过。 顺序表的思考与问题 1. 中间/头部的插入删除,时间复杂度为O(N) …

【python】flask模板渲染引擎Jinja2,通过后端数据渲染前端页面

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…

Spring Cloud 八:微服务架构中的数据管理

Spring Cloud 一:Spring Cloud 简介 Spring Cloud 二:核心组件解析 Spring Cloud 三:API网关深入探索与实战应用 Spring Cloud 四:微服务治理与安全 Spring Cloud 五:Spring Cloud与持续集成/持续部署(CI/C…

Eladmin-jpa基于SpringBoot和Vue的前后端分离后台管理系统​

在当今快速发展的软件开发领域,前后端分离的架构模式已经成为主流。这种架构模式不仅可以提高开发效率,还能使系统更加易于维护和扩展。Eladmin-jpa是一个基于Spring Boot 2.6.4、Spring Boot Jpa、JWT、Spring Security、Redis和Vue的前后端分离的后台管…

JS等比压缩图片方法

AI给出来的答案,AI真的能改变世界,以后程序员这个职业真的有可能不存在了。 function compressImage(image, callback) {// 创建一个 canvas 元素const canvas document.createElement(canvas);canvas.width 48;canvas.height 48;// 获取 canvas 的绘…

[WTL/Win32]_[初级]_[如何设置ListView的列宽不出现水平滚动条]

场景 开发WTL/Win32的程序时,经常会用到表格控件CListViewCtrl。这个控件需要设置列的宽度,当用完100%的宽度来平均分配给列宽时,一加载数据多,就会出现垂直滚动条后,水平滚动条也会同时出现的问题。怎么设置才能让水…

Stable Diffusion 本地部署教程

Stable Diffusion是一种用于构建和部署机器学习模型的开源工具。以下是在本地环境中部署 Stable Diffusion 的基本步骤: 步骤 1: 准备环境 确保你的系统中已经安装了以下软件和工具: Python(建议使用 Python 3.x)pip(Python 包管理工具)Docker(可选,用于容器化部署)…

【研发日记】Matlab/Simulink开箱报告(十)——Signal Routing模块模块

文章目录 前言 Signal Routing模块 虚拟模块和虚拟信号 Mux和Demux Vector Concatenate和Selector Bus Creator和Bus Selector 分析和应用 总结 前言 见《开箱报告,Simulink Toolbox库模块使用指南(五)——S-Fuction模块(C MEX S-Fun…

三、 mariadb数据库用户管理

1)查询有哪些用户 MariaDB> select user,host from mysql.user; ----------------- | user | host | ----------------- | root | 127.0.0.1 | | root | ::1 | | | localhost | | root | localhost | | | oldboy | | root | oldboy | ---------…

单链表专题(上)(顺序表链表线性表)

在开始之前思考一个顺序表的问题 1. 中间/头部的插⼊删除,时间 复杂度为O(N) 2. 增容需要申请新空间,拷⻉数据,释放旧空间。会有不⼩的消耗。 3. 增容⼀般是呈2倍的增⻓,势必会有⼀定的空间浪费。例如当前容量为100,…

类模板分文件编写

问题: 类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到 解决: 解决方式1:直接包含.cpp源文件 解决方式2:将声明和实现写到同一个文件中,并更改后缀名为.hpp,hpp是约定的名称…

订单系统-RPC快速入门

RPC快速入门 概述 关于rpc,只需要知道他是一种协议,项目之间能够远程调用函数。 快速入门 我们前边下载好的两个包,在idea中打开之后,我们创建这么几个文件夹。 至于是干什么的,以后细说。创建好之后我们在produc…

【Java 面试题】面向对象和面向过程的区别

面向对象和面向过程的区别? 面向对象编程(OOP)和面向过程编程(POP)是两种不同的编程范式,它们之间有一些重要的区别: 思想方式: 面向对象编程:将问题看作是一组对象之间…

【OpenStack】创建并部署自己的Web服务器和应用

【OpenStack】创建并部署自己的Web服务器和应用 目录 【OpenStack】创建并部署自己的Web服务器和应用云服务的工作原理查看Swift Python SDK连接发送请求使用其他SDK和其他语言运行项目克隆存储库安装项目依赖项定义环境配置启动服务器推荐超级课程: Docker快速入门到精通

C语言如何定义有参函教?

一、问题 有参函数是函数的重点部分,那么如何定义有参函数呢? 二、解答 有参函数定义的⼀般形式如下。 类型声明符 函数名(形式参数列表) {声明部分;语句; } 在形参列表中给出的参数称为形式参数,它们可以是各种类型…

从零开始搭建游戏服务器 第七节 创建GameServer

目录 前言正文创建GameServer模块修改配置创建NettyClient连接到登录服登录服修改创建协议游戏服注册到登录服 总结 前言 上一节我们使用自定义注解反射简化了协议解包和逻辑处理分发流程。 那么到了这里登录服登录服的架构已经搭建的差不多了,一些比较简单的、并发…

使用 Outline 构建 企业 or 个人 知识库面临的问题

前不久,我写了一篇文章,介绍《如何在本地部署安装 Outline》,我之所以写这篇文章,主要原因是我最近需要做一个项目,使用 Outline 来构建一个公司级知识库。所以我需要在本地先搭建一个,来撰写一些前期的文档…