在JavaScript中如何使用高阶函数

将另一个函数作为参数或将函数定义为返回值的函数称为高阶函数。

JavaScript 可以接受高阶函数。这种处理高阶函数的能力以及其他特性使 JavaScript 成为非常适合函数式编程的编程语言之一。

JavaScript 将函数视为一等公民

您可能听说过 JavaScript 函数是一等公民。这意味着 JavaScript 中的函数是对象。

它们具有 Object 类型的属性,可以作为变量的值赋值,并且可以像任何其他引用变量一样传递和返回。

一等函数赋予 JavaScript 特殊的能力,使我们能够从高阶函数中受益。

因为函数是对象,所以 JavaScript 是支持函数式编程的自然方法的流行编程语言之一。

高阶函数可以将函数作为参数

如果你做过很多 JavaScript Web 开发,你可能会遇到使用回调的函数。

回调函数是在所有其他操作完成后在操作结束时执行的函数。

通常,我们将此函数作为参数最后传递,在其他参数之后。它通常被内联定义为匿名函数。回调函数依赖于 JavaScript 处理高阶函数的能力。

JavaScript 是一种单线程语言。这意味着一次只能执行一个操作。

为了避免操作相互阻塞或阻塞系统的主线程(这会导致卡死),引擎确保所有操作按顺序执行。它们沿着这个单一线程排队,直到可以安全地发生另一个代码事务。

将函数作为参数传入并在父函数的其他操作完成后运行它的能力对于语言支持高阶函数至关重要。

JavaScript 中的回调函数允许异步行为,因此脚本可以在等待结果的同时继续执行其他函数或操作。

在处理可能在未确定的时间段后返回结果的资源时,传递回调函数的能力至关重要。

这种高阶函数模式在 Web 开发中非常有用。脚本可能会向服务器发送请求,然后需要在响应到达时对其进行处理,而无需了解服务器的网络延迟或处理时间。

Node.js 经常使用回调函数来有效利用服务器资源。这种异步方法在应用程序在执行功能之前等待用户输入的情况下也很有用。

示例:将警报函数传递给元素事件侦听器

document.getElementById("clicker").addEventListener("click", function() {
    alert("你点击了:" + this.id);
});

此脚本使用匿名内联函数来显示警报。

但它也可以很容易地使用单独定义的函数并将该命名函数传递给 addEventListener 方法:

var proveIt = function() {
    alert("你点击了:" + this.id);
};

document.getElementById("clicker").addEventListener("click", proveIt);

通过这样做,我们不仅演示了高阶函数。我们使我们的代码更具可读性和弹性,并为不同的任务(监听点击与提醒用户)分离了功能。

高阶函数如何支持代码可重用性

我们的 proveIt() 函数在结构上独立于它周围的代码,总是返回 id 被触发的任何元素的。这种函数设计方法是函数式编程的核心。

这段代码可以存在于您显示带有 id 元素的警报的任何上下文中,并且可以使用任何事件侦听器调用。

用单独定义和命名的函数替换内联函数的能力开辟了一个充满可能性的世界。

在函数式编程中,我们尝试开发不改变外部数据的纯函数,并且每次都为相同的输入返回相同的结果。

我们现在拥有一个基本工具来帮助我们开发一个小型的、有针对性的高阶函数库,您可以在任何应用程序中通用地使用它们。

注意:传递函数与传递函数对象

请注意,我们传递了proveIt而不是传递proveIt()给我们的addEventListener函数。

当您按名称传递不带括号的函数时,您传递的是函数对象本身。

当你用括号传递它时,你传递的是执行该函数的结果

使用高阶函数将函数作为结果返回

除了将函数作为参数之外,JavaScript 还允许函数返回其他函数作为结果。

这是有道理的,因为函数只是对象。对象(包括函数)可以定义为函数的返回值,就像字符串、数组或其他值一样。

但是作为结果返回一个函数是什么意思呢?

函数是分解问题和创建可重用代码的有效方法。当我们将函数定义为高阶函数的返回值时,它可以作为新函数的模板!

这打开了通向另一个函数式 JavaScript 魔法世界的大门。

假设我们把一句话中, 好难看 替换 好靓仔 这个词。

编写一个函数,对您传递给它的任何文本执行文本替换:

var fn = function(text) {
return text.replace(/好靓仔/ig, "好难看");
};
console.log(fn("程序员米粉好靓仔"));
// 程序员米粉好难看

那我现在又想改别的句子,替换字体。例如:vue框架是地球最好的框架。改成:react 框架是地球最好的框架。

var fn = function(text) {
return text.replace(/vue/ig, "react");
};
console.log(fn("vue框架是地球最好的框架"));
// react 框架是地球最好的框架

这样我们写起来,是可以改,但是看起来有点麻烦。有没别的办法可以更简单方便。这而且会使您的代码更脆弱,更难阅读。在这种情况下,我们可以使用高阶函数作为解决方案。

构建模板高阶函数

您真正想要的是能够将模板函数中的任何术语替换为任何其他术语的灵活性,并将该行为定义为基础函数,您可以从中构建新的自定义函数。

通过将函数分配为返回值的能力,JavaScript 提供了使该场景更加方便的方法:

var attitude = function(original, replacement, source) {
    return function(source) {
        return source.replace(original, replacement);
    };
};

var snakify = attitude(/好靓仔/ig, "好难看");
var hippify = attitude(/vue/ig, "react");

console.log(snakify("程序员米粉好靓仔"));

console.log(hippify("vue框架是地球最好的框架"));

我们所做的是将执行实际工作的代码隔离到一个通用且可扩展的 attitude 函数中。它封装了使用原始短语作为初始值修改任何输入字符串所需的所有工作,并输出带有某种态度的替换短语。

当我们将这个新函数定义为对 attitude 高阶函数的引用时,我们得到了什么,并预先填充了它所采用的前两个参数?它允许新函数获取您传递给它的任何文本,并在我们定义为attitude函数输出的返回函数中使用该参数。

JavaScript 函数不关心传递给它们的参数的数量。

如果缺少第二个参数,它会将其视为未定义。当我们选择不提供第三个参数或任何数量的附加参数时,它也会这样做。

此外,您可以稍后传递该附加参数。当您定义了您希望调用的高阶函数时,您可以执行此操作,如刚才演示的那样。

只需将其定义为对函数的引用,高阶函数返回一个或多个未定义的参数。

如果需要,请重复几次,以便您完全了解正在发生的事情。

我们正在创建一个返回另一个函数的模板高阶函数。然后我们将新返回的函数定义为模板函数的自定义实现,减去一个属性。

您以这种方式创建的所有函数都将从高阶函数继承工作代码。但是,您可以使用不同的默认参数预定义它们。

你已经在使用高阶函数

高阶函数对于 JavaScript 的工作方式是如此基础,你已经在使用它们了。

每次传递匿名或回调函数时,实际上都是在获取传递函数返回的值,并将其用作另一个函数的参数(例如使用箭头函数)。

开发人员在学习 JavaScript 的早期就熟悉了高阶函数。它是 JavaScript 设计的固有特性,以至于可能要到以后才需要了解箭头函数或回调函数的概念。

分配返回其他函数的函数的能力扩展了 JavaScript 的便利性。高阶函数允许我们创建自定义命名的函数,以使用来自一阶函数的共享模板代码执行专门的任务。

这些函数中的每一个都可以继承未来在高阶函数中所做的任何改进。这有助于我们避免代码重复,并保持我们的源代码干净和可读。

如果您确保您的函数是纯函数(它们不会更改外部值并且对于任何给定的输入总是返回相同的值),您可以创建测试来验证您的代码更改不会在您更新一阶函数时破坏任何内容.

结论

现在您知道了高阶函数是如何工作的,您可以开始思考如何在您自己的项目中利用该概念。

JavaScript 的一大优点是您可以将函数式技术与您已经熟悉的代码混合在一起。

尝试一些实验。即使您开始使用高阶函数,您也会很快熟悉它们提供的额外灵活性。

现在对高阶函数进行一点工作可以在未来几年内改进您的代码。

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值