广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >如何掌握高阶的函数技术
  • 922
分享到

如何掌握高阶的函数技术

2024-04-02 19:04:59 922人浏览 泡泡鱼
摘要

这篇文章主要介绍“如何掌握高阶的函数技术”,在日常操作中,相信很多人在如何掌握高阶的函数技术问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何掌握高阶的函数技术”的疑惑有所帮

这篇文章主要介绍“如何掌握高阶的函数技术”,在日常操作中,相信很多人在如何掌握高阶的函数技术问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何掌握高阶的函数技术”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、高阶函数

数学和计算机科学中,高阶函数是至少满足下列一个条件的函数:

  • 接受一个或多个函数作为输入;

  • 输出一个函数。

接收一个或多个函数作为输入,即函数作为参数传递。这种应用场景,相信很多人都不会陌生。比如常用的 Array.prototype.map() 和  Array.prototype.filter() 高阶函数:

// Array.prototype.map 高阶函数 const array = [1, 2, 3, 4]; const map = array.map(x => x * 2); // [2, 4, 6, 8]  // Array.prototype.filter 高阶函数 const Words = ['semlinker', 'kakuqo', 'lolo', 'abao']; const result = words.filter(word => word.length > 5); // ["semlinker", "kakuqo"]

而输出一个函数,即调用高阶函数之后,会返回一个新的函数。我们日常工作中,常见的 debounce 和 throttle  函数就满足这个条件,因此它们也可以被称为高阶函数。

如何掌握高阶的函数技术

二、函数组合

数组合就是将两个或两个以上的函数组合生成一个新函数的过程:

const compose = function (f, g) {   return function (x) {     return f(g(x));   }; };

在以上代码中,f 和 g 都是函数,而 x 是组合生成新函数的参数。

2.1 函数组合的作用

项目开发过程中,为了实现函数的复用,我们通常会尽量保证函数的职责单一,比如我们定义了以下功能函数:

如何掌握高阶的函数技术

在拥有以上功能函数的基础上,我们就可以自由地对函数进行组合,来实现特定的功能:

function lowerCase(input) {   return input && typeof input === "string" ? input.toLowerCase() : input; }  function upperCase(input) {   return input && typeof input === "string" ? input.toUpperCase() : input; }  function trim(input) {   return typeof input === "string" ? input.trim() : input; }  function split(input, delimiter = ",") {   return typeof input === "string" ? input.split(delimiter) : input; }  const trimLowerCaseAndSplit = compose(trim, lowerCase, split); trimLowerCaseAndSplit(" a,B,C "); // ["a", "b", "c"]

在以上的代码中,我们通过 compose 函数实现了一个 trimLowerCaseAndSplit  函数,该函数会对输入的字符串,先执行去空格处理,然后在把字符串中包含的字母统一转换为小写,最后在使用 ,  分号对字符串进行拆分。利用函数组合的技术,我们就可以很方便的实现一个 trimUpperCaseAndSplit 函数。

2.2 组合函数的实现

function compose(...funcs) {   return function (x) {     return funcs.reduce(function (arg, fn) {       return fn(arg);     }, x);   }; }

在以上的代码中,我们通过 Array.prototype.reduce 方法来实现组合函数的调度,对应的执行顺序是从左到右。这个执行顺序与 linux  管道或过滤器的执行顺序是一致的。

如何掌握高阶的函数技术

不过如果你想从右往左开始执行的话,这时你就可以使用 Array.prototype.reduceRight 方法来实现。

其实每当看到 compose 函数,阿宝哥就情不自禁想到 “如何更好地理解中间件和洋葱模型” 这篇文章中介绍的 compose 函数:

function compose(middleware) {   // 省略部分代码   return function (context, next) {     let index = -1;     return dispatch(0);     function dispatch(i) {       if (i <= index)         return Promise.reject(new Error("next() called multiple times"));       index = i;       let fn = middleware[i];       if (i === middleware.length) fn = next;       if (!fn) return Promise.resolve();       try {         return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));       } catch (err) {         return Promise.reject(err);       }     }   }; }

利用上述的 compose 函数,我们就可以实现以下通用的任务处理流程:

如何掌握高阶的函数技术

三、柯里化

柯里化(Currying)是一种处理函数中含有多个参数的方法,并在只允许单一参数的框架中使用这些函数。这种转变是现在被称为 “柯里化”  的过程,在这个过程中我们能把一个带有多个参数的函数转换成一系列的嵌套函数。它返回一个新函数,这个新函数期望传入下一个参数。当接收足够的参数后,会自动执行原函数。

在理论计算机科学中,柯里化提供了简单的理论模型,比如:在只接受一个单一参数的 lambda 演算中,研究带有多个参数的函数的方式。与柯里化相反的是  Uncurrying,一种使用匿名单参数函数来实现多参数函数的方法。比如:

const func = function(a) {   return function(b) {     return a * a + b * b;   } }  func(3)(4); // 25

Uncurrying 不是本文的重点,接下来我们使用 Lodash 提供的 curry 函数来直观感受一下,对函数进行 “柯里化” 处理之后产生的变化:

const abc = function(a, b, c) {   return [a, b, c]; };   const curried = _.curry(abc);   curried(1)(2)(3); // => [1, 2, 3] curried(1, 2)(3); // => [1, 2, 3] curried(1, 2, 3); // => [1, 2, 3]

_.curry(func, [arity=func.length])

创建一个函数,该函数接收 func 的参数,要么调用func返回的结果,如果 func 所需参数已经提供,则直接返回 func  所执行的结果。或返回一个函数,接受余下的func 参数的函数,可以使用 func.length 设置需要累积的参数个数。

来源:https://www.lodashjs.com/docs/lodash.curry

这里需要特别注意的是,在数学和理论计算机科学中的柯里化函数,一次只能传递一个参数。而对于 javascript  语言来说,在实际应用中的柯里化函数,可以传递一个或多个参数。好的,介绍完柯里化的相关知识,接下来我们来介绍柯里化的作用。

3.1 柯里化的作用

3.1.1 参数复用

function buildUri(scheme, domain, path) {   return `${scheme}://${domain}/${path}`; }  const profilePath = buildUri("Https", "GitHub.com", "semlinker/semlinker"); const awesomeTsPath = buildUri("https", "github.com", "semlinker/awesome-typescript");

在以上代码中,首先我们定义了一个 buildUri 函数,该函数可用于构建 uri 地址。接着我们使用 buildUri 函数构建了阿宝哥 Github  个人主页 和 awesome-typescript 项目的地址。对于上述的 uri 地址,我们发现 https 和 github.com  这两个参数值是一样的。

假如我们需要继续构建阿宝哥其他项目的地址,我们就需要重复设置相同的参数值。那么有没有办法简化这个流程呢?答案是有的,就是对 buildUri  函数执行柯里化处理,具体处理方式如下:

const _ = require("lodash");  const buildUriCurry = _.curry(buildUri); const myGithubPath = buildUriCurry("https", "github.com"); const profilePath = myGithubPath("semlinker/semlinker"); const awesomeTsPath = myGithubPath("semlinker/awesome-typescript");

3.1.2 延迟计算/运行

const add = function (a, b) {   return a + b; };  const curried = _.curry(add); const plusOne = curried(1);

在以上代码中,通过对 add 函数执行 “柯里化” 处理,我们可以实现延迟计算。好的,简单介绍完柯里化的作用,我们来动手实现一个柯里化函数。

3.2 柯里化的实现

现在我们已经知道了,当柯里化后的函数接收到足够的参数后,就会开始执行原函数。而如果接收到的参数不足的话,就会返回一个新的函数,用来接收余下的参数。基于上述的特点,我们就可以自己实现一个  curry 函数:

function curry(func) {   return function curried(...args) {     if (args.length >= func.length) { // 通过函数的length属性,来获取函数的形参个数       return func.apply(this, args);     } else {       return function (...args2) {         return curried.apply(this, args.concat(args2));       };     }   } }

四、偏函数应用

在计算机科学中,偏函数应用(Partial  Application)是指固定一个函数的某些参数,然后产生另一个更小元的函数。而所谓的元是指函数参数的个数,比如含有一个参数的函数被称为一元函数。

偏函数应用(Partial Application)很容易与函数柯里化混淆,它们之间的区别是:

偏函数应用是固定一个函数的一个或多个参数,并返回一个可以接收剩余参数的函数;

柯里化是将函数转化为多个嵌套的一元函数,也就是每个函数只接收一个参数。

了解完偏函数与柯里化的区别之后,我们来使用 Lodash 提供的 partial 函数来了解一下它如何使用。

4.1 偏函数的使用

function buildUri(scheme, domain, path) {   return `${scheme}://${domain}/${path}`; }  const myGithubPath = _.partial(buildUri, "https", "github.com"); const profilePath = myGithubPath("semlinker/semlinker"); const awesomeTsPath = myGithubPath("semlinker/awesome-typescript");

_.partial(func, [partials])

创建一个函数。该函数调用 func,并传入预设的 partials 参数。

4.2 偏函数的实现

偏函数用于固定一个函数的一个或多个参数,并返回一个可以接收剩余参数的函数。基于上述的特点,我们就可以自己实现一个 partial 函数:

function partial(fn) {   let args = [].slice.call(arguments, 1);   return function () {     const newArgs = args.concat([].slice.call(arguments));     return fn.apply(this, newArgs);   }; }

4.3 偏函数实现 vs 柯里化实现

如何掌握高阶的函数技术

五、惰性函数

由于不同浏览器之间存在一些兼容性问题,这导致了我们在使用一些 WEB api 时,需要进行判断,比如:

function addHandler(element, type, handler) {   if (element.addEventListener) {     element.addEventListener(type, handler, false);   } else if (element.attachEvent) {     element.attachEvent("on" + type, handler);   } else {     element["on" + type] = handler;   } }

在以上代码中,我们实现了不同浏览器 添加事件监听  的处理。代码实现起来也很简单,但存在一个问题,即每次调用的时候都需要进行判断,很明显这是不合理的。对于上述这个问题,我们可以通过惰性载入函数来解决。

5.1 惰性载入函数

所谓的惰性载入就是当第 1 次根据条件执行函数后,在第 2 次调用函数时,就不再检测条件,直接执行函数。要实现这个功能,我们可以在第 1  次条件判断的时候,在满足判断条件的分支中覆盖掉所调用的函数,具体的实现方式如下所示:

function addHandler(element, type, handler) {   if (element.addEventListener) {     addHandler = function (element, type, handler) {       element.addEventListener(type, handler, false);     };   } else if (element.attachEvent) {     addHandler = function (element, type, handler) {       element.attachEvent("on" + type, handler);     };   } else {     addHandler = function (element, type, handler) {       element["on" + type] = handler;     };   }   // 保证首次调用能正常执行监听   return addHandler(element, type, handler); }

除了使用以上的方式,我们也可以利用自执行函数来实现惰性载入:

const addHandler = (function () {   if (document.addEventListener) {     return function (element, type, handler) {       element.addEventListener(type, handler, false);     };   } else if (document.attachEvent) {     return function (element, type, handler) {       element.attachEvent("on" + type, handler);     };   } else {     return function (element, type, handler) {       element["on" + type] = handler;     };   } })();

通过自执行函数,在代码加载阶段就会执行一次条件判断,然后在对应的条件分支中返回一个新的函数,用来实现对应的处理逻辑。

六、缓存函数

缓存函数是将函数的计算结果缓存起来,当下次以同样的参数调用该函数时,直接返回已缓存的结果,而无需再次执行函数。这是一种常见的以空间换时间的性能优化手段。

要实现缓存函数的功能,我们可以把经过序列化的参数作为 key,在把第 1 次调用后的结果作为 value  存储到对象中。在每次执行函数调用前,都先判断缓存中是否含有对应的 key,如果有的话,直接返回该 key  对应的值。分析完缓存函数的实现思路之后,接下来我们来看一下具体如何实现:

function memorize(fn) {   const cache = Object.create(null); // 存储缓存数据的对象   return function (...args) {     const _args = JSON.stringify(args);     return cache[_args] || (cache[_args] = fn.apply(fn, args));   }; };

定义完 memorize 缓存函数之后,我们就可以这样来使用它:

let complexCalc = (a, b) => {   // 执行复杂的计算 };  let memoCalc = memorize(complexCalc); memoCalc(666, 888); memoCalc(666, 888); // 从缓存中获取

到此,关于“如何掌握高阶的函数技术”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: 如何掌握高阶的函数技术

本文链接: https://www.lsjlt.com/news/84352.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何掌握高阶的函数技术
    这篇文章主要介绍“如何掌握高阶的函数技术”,在日常操作中,相信很多人在如何掌握高阶的函数技术问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何掌握高阶的函数技术”的疑惑有所帮...
    99+
    2022-10-19
  • 想要更好地掌握 Python 开发技术中的 NumPy 函数,这些技巧必须掌握!
    Python 是一种广泛使用的编程语言,它在数据科学、人工智能、机器学习和其他领域都有着广泛的应用。NumPy 是 Python 中一个非常重要的库,它提供了高效的数值计算和数组操作功能。在 Python 开发中,掌握 NumPy 函数是非...
    99+
    2023-06-03
    开发技术 numy 函数
  • PHP开发技术:函数教程,你掌握了吗?
    PHP作为一种流行的服务器端脚本语言,其内置函数的使用是必不可少的。函数的作用是将一段代码封装成可重复使用的代码块,方便程序员进行代码的复用和维护。本篇文章将介绍PHP中的常用函数,并通过实例演示它们的使用方法。 strlen()函数 ...
    99+
    2023-08-09
    开发技术 教程 函数
  • Go 函数编程:掌握技巧,成为高手!
    Go 语言作为一门现代化的编程语言,被广泛应用于后端服务开发、网络编程、云计算等领域。在 Go 语言中,函数编程被视为一种重要的编程思想,它可以提高代码的可读性和可维护性,同时也能够让程序员编写出更加优雅的代码。本篇文章将介绍一些 Go 函...
    99+
    2023-08-19
    函数 开发技术 学习笔记
  • PHP开发技术教程:如何轻松掌握函数的使用方法?
    PHP是一种流行的Web编程语言,它是一种开源的脚本语言,用于开发动态Web应用程序。PHP具有广泛的应用领域,如网站开发、Web应用程序和服务器端脚本,因此掌握PHP开发技术是非常重要的。 在PHP中,函数是一种非常重要的概念,它可以帮...
    99+
    2023-08-09
    开发技术 教程 函数
  • 想成为一名Go开发技术高手?Django函数是你必须掌握的技能!
    作为一名Go开发技术高手,你必须掌握Django函数。这个强大的框架提供了许多函数,可以帮助你更快、更轻松地开发应用程序。在本文中,我们将介绍一些最常用的Django函数,以及如何使用它们来提高你的开发效率。 一、Django函数简介 Dj...
    99+
    2023-10-26
    开发技术 django 函数
  • 高效掌握JDBC技术(二)| 掌握ORM思想 | 定义连接数据库的工具类
    ✅作者简介:C/C++领域新星创作者、CSDN内容合伙人,喜欢学习后端语言的大学生 ✨精品专栏:C++面向对象核心 🔥系列专栏:JDBC技术 📃推荐一款模拟面试、刷题神器👉注册免费刷题 ...
    99+
    2023-08-16
    数据库 mysql 大数据
  • 掌握MySQL半同步复制技术handle_slave_io函数调用read_event函数方法
    下面讲讲关于掌握MySQL半同步复制技术handle_slave_io函数调用read_event函数方法,文字的奥妙在于贴近主题相关。所以,闲话就不谈了,我们直接看下文吧,相信看完掌握MySQL半同步复制...
    99+
    2022-10-18
  • 开发技术专题:掌握PHP异步编程函数的核心技巧
    PHP是一种广泛使用的后端编程语言,其异步编程函数可让程序在执行某些耗时操作时不会阻塞其他代码的执行。在本文中,我们将深入探讨PHP异步编程函数的核心技巧,帮助读者更好地掌握这一重要开发技术。 一、什么是PHP异步编程函数 在传统的同步编程...
    99+
    2023-09-13
    异步编程 开发技术 函数
  • 学习笔记:如何高效地掌握 Java 缓存技术?
    Java 缓存技术是开发 Java 应用程序时必须掌握的一项技术。缓存技术可以帮助我们提高应用程序的性能,减少对数据库等资源的访问次数,提高系统的响应速度。本文将介绍如何高效地掌握 Java 缓存技术,包括缓存的原理、常见的缓存技术以及如何...
    99+
    2023-10-06
    缓存 学习笔记 面试
  • 如何快速掌握Python中的循环技术
    这篇文章主要讲解了“如何快速掌握Python中的循环技术”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何快速掌握Python中的循环技术”吧!1. 使用enumerate()循环整个序列当...
    99+
    2023-06-15
  • 如何掌握函数式编程
    这篇文章主要介绍“如何掌握函数式编程”,在日常操作中,相信很多人在如何掌握函数式编程问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何掌握函数式编程”的疑惑有所帮助!接下来,...
    99+
    2022-10-19
  • 你是否真正掌握了 Java 对象开发技术中的函数?
    Java 对象开发技术中的函数是一个非常重要的主题,因为函数是 Java 开发中最常用的编程结构之一。尽管 Java 有很多内置函数,但是开发人员需要掌握自定义函数的技巧,以便在开发过程中更好地管理代码和提高效率。 首先,让我们来看看函数的...
    99+
    2023-07-05
    对象 开发技术 函数
  • Python、Unix、Laravel、大数据:如何快速掌握这些技术?
    随着现代技术的快速发展,各行各业对于技术人才的需求也越来越高。Python、Unix、Laravel、大数据等技术已经成为了当前最受欢迎的技术之一。那么如何快速掌握这些技术呢?本文将会为大家介绍如何快速掌握Python、Unix、Lara...
    99+
    2023-11-07
    unix laravel 大数据
  • Java开发者必须掌握的大数据技术?
    随着大数据时代的到来,越来越多的企业开始注重数据的价值和利用。在这个过程中,Java作为一种非常流行的编程语言,也扮演着非常重要的角色。Java开发者需要掌握一些大数据技术,以便更好地利用数据。本文将介绍一些Java开发者必须掌握的大数据...
    99+
    2023-07-04
    大数据 ide 数据类型
  • ASP 函数教程:掌握打包技巧,让您的代码更加高效!
    ASP(Active Server Pages)是一种开发动态网站的技术,它使用 VBScript 或 JScript 这样的脚本语言来创建动态内容。在 ASP 中,函数是一种重要的编程元素,它可以让我们将代码逻辑分解成小块,提高代码的可...
    99+
    2023-09-13
    函数 教程 打包
  • numpy编程算法必备:掌握go函数的技巧
    numpy是Python中一个非常重要的库,它为科学计算提供了强大的支持。在numpy中,go函数是一个非常有用的算法,可以用于对数组进行元素间的操作。掌握go函数的技巧对于numpy编程算法是必不可少的。本文将介绍go函数的基本用法,以及...
    99+
    2023-06-28
    函数 numpy 编程算法
  • 如何使用 ASP 函数 load git?这是您必须掌握的技能!
    ASP 函数 load git 是一种非常有用的技能,可以帮助您轻松地将代码存储到 Git 仓库中,并且可以方便地管理您的代码版本。在本文中,我们将介绍如何使用 ASP 函数 load git,让您掌握这个重要的技能。 首先,让我们看一下 ...
    99+
    2023-10-31
    函数 load git
  • Python 面试备战:如何掌握 Django 中 Load 函数的优化技巧?
    在 Django 中, Load 函数是非常常用的函数之一,它用于从数据库中读取数据。但是,如果不注意优化,Load 函数会成为应用程序的瓶颈,导致程序运行变慢。因此,掌握 Django 中 Load 函数的优化技巧是非常重要的。 在本文...
    99+
    2023-07-30
    面试 django load
  • 大数据重定向必备技能:掌握 Python 的 load 函数
    大数据是当今社会发展的重要方向,而Python语言是一种非常适合处理大数据的编程语言。在Python中,load函数是一个非常重要的函数,它可以帮助我们对大量数据进行处理和转换。在本文中,我们将探讨load函数的基本知识和如何使用它来处理大...
    99+
    2023-10-17
    大数据 重定向 load
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作