在 JavaScript 使用高阶函数的方法你知道了吗

avaScript 非常适合函数式编程的特点之一是它可以接受高阶函数。高阶函数是一个可以将另一个函数作为参数的函数,或者返回一个函数作为结果的函数。

一等函数:JavaScript 中作为对象的函数
您可能听说过 JavaScript 将函数视为一等公民。这意味着 JavaScript 中的函数被视为对象。它们具有 type Object,可以作为变量的值赋值,并且可以像任何其他引用变量一样传递和返回。

这种原生能力赋予了 JavaScript 在函数式编程方面的特殊能力。因为函数是对象,所以该语言支持一种非常自然的函数式编程方法。事实上,它是如此自然,我敢打赌你一直在使用它,甚至没有考虑过它

高阶函数如何将函数作为参数
如果您做过很多基于 Web 的 JavaScript 编程或前端开发,您可能会遇到使用回调的函数。回调是在所有其他操作完成后在操作结束时执行的函数。通常这个回调函数作为函数的最后一个参数传入。通常,它被内联定义为匿名函数。

由于 JavaScript 是单线程的,这意味着一次只发生一个操作,因此将要发生的每个操作都沿着这个单线程排队。在父函数的其余操作完成后传入要执行的函数的策略是支持高阶函数的语言的基本特征之一。它允许异步行为,因此脚本可以在等待结果的同时继续执行。在处理可能在未确定的时间段后返回结果的资源时,传递回调函数的能力至关重要。

这在 Web 编程环境中非常有用,其中脚本可能会将 Ajax 请求发送到服务器,然后需要在响应到达时处理响应,而事先不知道服务器上的网络延迟或处理时间。Node.js 经常使用回调来最有效地利用服务器资源。这种方法在应用程序在执行功能之前等待用户输入的情况下也很有用。

例如,考虑这个简单的 JavaScript 片段,它向按钮添加了一个事件侦听器。

知识点


document.getElementById("clicker").addEventListener("click", function() {
alert("you triggered " + this.id);
});
此脚本使用匿名内联函数来显示警报。但它可以很容易地使用单独定义的函数,并将该命名函数传递给addEventListener方法

var proveIt = function() {
alert("you triggered " + this.id);
};```

document.getElementById("clicker").addEventListener("click", proveIt);
请注意,我们传递了proveIt而不是传递proveIt()给我们的addEventListener函数。当您按名称传递不带括号的函数时,您传递的是函数对象本身。当你用括号传递它时,你传递的是执行该函数的结果。

我们的小proveIt()函数在结构上独立于它周围的代码,总是返回id被触发的任何元素的。这段代码可以存在于您希望id使用元素显示警报的任何上下文中,并且可以使用任何事件侦听器调用。

用单独定义和命名的函数替换内联函数的能力开辟了一个充满可能性的世界。当我们尝试开发不改变外部数据的纯函数,并且每次都为相同的输入返回相同的结果时,我们现在拥有一个基本工具来帮助我们开发一个可以使用的小型目标函数库一般在任何应用程序中。

使用高阶函数将函数作为结果返回
除了将函数作为参数之外,JavaScript 还允许函数返回其他函数作为结果。这是完全合理的,因为函数只是对象,它们可以像任何其他值一样返回。

但是作为结果返回的一个函数是什么意思呢?将一个函数定义为另一个函数的返回值允许您创建可用作模板来创建新函数的函数。于是打开了通向另一个函数式 JavaScript 魔法世界的大门。

例如,假设您已经厌倦了阅读所有这些关于千禧一代的特殊性的文章,并且您决定每次出现时都将千禧一代一词替换为短语Snake People 。您的冲动可能只是编写一个函数,对您传递给它的任何文本执行文本替换

```var snakify = function(text) {
return text.replace(/millenials/ig, "Snake People");
};
console.log(snakify("The Millenials are always up to something."));
// The Snake People are always up to something.```
这行得通,但它非常特定于这种情况。你也厌倦了听到婴儿潮一代的消息。您还想为它们创建一个自定义函数。但即使使用如此简单的函数,您也不想重复您编写的代码:

```var hippify = function(text) {
return text.replace(/baby boomers/ig, "Aging Hippies");
};
console.log(hippify("The Baby Boomers just look the other way."));
// The Aging Hippies just look the other way.```
但是,如果您决定做一些更有趣的事情来保留原始字符串中的大小写呢?您必须修改您的两个新功能才能做到这一点。这很麻烦,而且会使您的代码更脆弱,更难阅读。

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

由于能够返回函数而不是值,JavaScript 提供了使该场景更加方便的方法:

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

var snakify = attitude(/millenials/ig, "Snake People");
var hippify = attitude(/baby boomers/ig, "Aging Hippies");

console.log(snakify("The Millenials are always up to something."));
// The Snake People are always up to something.
console.log(hippify("The Baby Boomers just look the other way."));
// The Aging Hippies just look the other way.```
我们所做的是将执行实际工作的代码隔离到一个通用且可扩展的attitude函数中,该函数封装了使用原始短语和带有某种态度的替换短语来修改任何输入字符串所需的所有工作。

将新函数定义为对该attitude函数的引用,并预先填充它所采用的前两个参数,从而允许新函数接受您传递给它的任何参数并将其用作函数返回的内部函数中的源文本attitude。

我们在这里利用了这样一个事实,即 JavaScript 函数不关心它们是否传递了与最初定义的参数数量相同的参数。如果缺少参数,该函数只会将缺少的参数视为未定义。

另一方面,当被调用的函数以我们刚刚演示的方式定义时,可以稍后传入额外的参数,作为对从另一个函数返回的函数的引用,该函数的参数(或更多)未定义。

如果需要,请重复几次,以便您完全了解正在发生的事情。我们正在创建一个返回另一个函数的模板函数。然后我们将新返回的函数定义为模板函数的自定义实现,减去一个属性。以这种方式创建的所有函数都将从模板函数继承相同的工作代码,但可以使用不同的默认参数进行预定义。 知识点

你已经在使用高阶函数
高阶函数对于 JavaScript 的工作方式是如此基础,你已经在使用它们了。每次传递匿名函数或回调时,实际上都是在获取传递函数返回的值,并将其用作另一个函数的参数(例如使用箭头函数)。

函数返回其他函数的能力扩展了 JavaScript 的便利性,允许我们创建自定义命名的函数来使用共享模板代码执行专门的任务。这些小功能中的每一个都可以继承原始代码中的任何改进,这有助于我们避免代码重复,并保持原始代码的清洁和可读性。

作为一个额外的好处,如果你确保你的函数是纯的,因此它们不会改变外部值,并且对于任何给定的输入它们总是返回相同的值,你就可以很好地创建测试套件来验证你的代码更新模板函数时,更改不会破坏您所依赖的任何内容。

开始思考如何在自己的项目中利用这种方法。JavaScript 的一大优点是您可以将函数式技术与您已经熟悉的代码混合在一起。尝试一些实验。您可能会惊讶于使用高阶函数可以轻松地改进您的代码。

如果本文对你有帮助,别忘记给我个3连 ,点赞,转发,评论,,咱们下期见。

收藏 等于白嫖,点赞才是真情

亲爱的小伙伴们,有需要JAVA面试文档资料请点赞+转发,关注我后,私信我333就可以领取免费资料哦 
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容