JavaScript与函数式编程

更新日期: 2020-04-20阅读: 2.3k标签: 编程

绝大多数编程语言都会有函数的概念(或者说所有的?我不太确定),他们都可以做出类似的操作:

function(x) {
  return x * x
}

但是Javascript更适合函数式编程,因为函数对于js来说,是一等公民

我们可以把匿名函数赋值给一个变量,比如:

let pow = function(x) {
  return x * x
}

然后我们可以将这个函数赋值给另一个变量:

let comeon = pow
comeon(x)

这样做和直接调用pow(x)是一样的效果。

甚至于我们可以将函数作为参数传入另一个函数,这样,诸多小函数可以汇聚在一起,变得异常强大!


filter()

OK,我们接下来看一些比较基础的例子。

首先是filter(),这是我最喜欢的函数之一。filter()方法会创建一个新的数组,并且我们可以传入一个判断函数,将符合条件的元素,放入新的数组。

现在我们有一个数组,里面存放了很多游戏,每个元素都记录了该游戏需要花多少钱:

let games = [
  {
    name: '英雄联盟',
    cost: 45
  },
  {
    name: '穿越火线',
    cost: 888
  },
  {
    name: '魔兽世界',
    cost: 75
  },
  {
    name: '征途',
    cost: 1000000
  }
]

然后我们需要找出,花费不超过一百元的游戏,该怎么做呢?

可能是这样:

let target = []
for(let i = 0; i < games.length; i++) {
  if(games[i].cost <= 100) {
    target.push(games[i])
  }
}

这是大家从大学开始学C语言的时候就会用的方法。但是我现在想用filter()方法重写它:

let target = games.filter((game) => {
  return game.cost <= 100
})

Wow! Awesome!

我稍微解释一下,防止有同学没有看懂,这里传入了一个函数,函数接收了一个参数,这个参数就是games的每一个元素依次传入的值,在每一次传入之后,我们都返回一个逻辑值,这个逻辑值取决于该游戏的cost是否小于100,如果返回了true该元素就会被放到新的数组里去,反之同理。

注意:

  • filter()不会对空数组进行检测
  • filter()不会改变原始数组

实际上,filter内部的处理方法可能和我们使用for循环一模一样!但是我们利用函数式编程,写了更少的代码、更少的逻辑。Less code! Less time! Less bug!

这就是函数式编程的美妙之处。


map()

我们现在先看回之前写的数组:

let games = [
  {
    name: '英雄联盟',
    cost: 45
  },
  {
    name: '穿越火线',
    cost: 888
  },
  {
    name: '魔兽世界',
    cost: 75
  },
  {
    name: '征途',
    cost: 1000000
  }
]

现在我们要把每一款游戏的名字都拿出来,组成一个新的数组。

这种操作是非常常见的,比如我们使用react,向服务器请求了JSON数据,接下来需要在这里渲染名字,那里渲染价格……等等。

let gameName = games.map((item) => {
  return item.name
})

我们甚至可以做出更多的骚操作,比如说:

let gameName = games.map((item) => {
  return `${item.name}是一个${item.cost > 100? '坑钱游戏':'良心游戏'}`
})

得到结果["英雄联盟是一个良心游戏", "穿越火线是一个坑钱游戏", "魔兽世界是一个良心游戏", "征途是一个坑钱游戏"]

Wow! Awesome! 只能用优雅两个字来形容!


reduce()

reduce()单词本身是减少的意思,但是实际上你可以将reduce()理解为求和(事实并不如此,reduce更加强大且灵活,但是此时可以暂时这么理解,更多特性可以在下一节看到)。

语言太过苍白无力,我们来看看代码:

let numbers = [1, 2, 3, 4, 5]
let sum = numbers.reduce((total, item) => total + item)

这里是利用了箭头函数可以省略return的特性。

这里的传入的函数接收了两个参数(实际上可以接收四个,但这里不需要后面两个),这两个参数通过英文应该就可以看懂。

reduce()方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。

注意: reduce()对于空数组是不会执行回调函数的。

这里可以给一个初始值:

let numbers = [1, 2, 3, 4, 5]
let sum = numbers.reduce((total, item) => {
  return total + item
}, 10)

之前的和是15,这次加上了一个初始值,就是25了。


实践

假设我们有一个TXT文件。

徐航宇	游泳	4分钟
徐航宇	跑步	1分钟
徐航宇	跳远	3米
刘好	游泳	5分钟
刘好	跑步	2分钟
刘好	跳远	1米

我们用node去读取他,让它变成一个JSON对象,就像这样:

{
  "徐航宇": [
    {
      "项目": "游泳",
      "时间": "4分钟"
    },
    {
      "项目":"跑步",
      "时间":"1分钟"
    }
  ],
  "刘好": [
    // ...
  ]
}

上代码!

import fs from 'fs'

let output = fs.readFileSync('data.txt', 'utf-8')
	.trim() // 去掉字符串头尾的空格,返回新数组
	.split('\n') // 在换行处截断,组成数组
	.map(line => line.split('\t')) // 每一行根据制表符断开,组成数组

这一步之后,我们应该得到什么?

[
  ["徐航宇", "游泳", "4分钟"],
	["徐航宇", "跑步", "1分钟"],
	["徐航宇", "跳远", "3米"],
	["刘好", "游泳", "5分钟"],
	["刘好", "跑步", "2分钟"],
	["刘好", "跳远", "1米"]
]

接下来想要变成对象,该怎么做呢?

首先第一步,我们想一想,要想变成最终的JSON数据,我们需要对每一项进行处理:

  • 把每一个数组的第一个作为对象的属性名
  • 把每一个数组的二三项组成新的对象,放入该属姓名的值中

接下来就该reduce()出场了:

.reduce((customer, line) => {
  	// 提取每个数组的第一项,作为传入对象的属姓名
  	// 如果该项是以前没有的,那么将其初始化为空数组
  	// 如果该项以前有,那么就不动他
    customer[line[0]] = customer[line[0]] === undefined ? [] : customer[line[0]]
		customer[line[0]].push({
      name: line[1],
      time: line[2]
    })
    return customer
  }, {})

这样就成功了!


总结

总而言之,函数式编程如果归根结底,和直接写没有任何区别。但是它提供给了我们一种写更少的代码,完成更多的事情的方法。

人是难免会出错的,代码量越大、错误可能就会越多,所以更少代码的函数式编程,往往意味着:更少的bug。

(完)

链接: https://fly63.com/article/detial/8665

程序员的笔记,编程写软件学到的 7 件事

如果你真的做出了一些东西,在面对那些令人眼花缭乱的理论知识,或是和你相似甚至比你做的更糟糕的人时大可不必谦虚。在一天结束之时,正是那些在战壕中的开发者——构建、测试和开发了代码的人,真正做了事情。

自学编程的六个技巧总结

这些事情可以帮助新手在他们漫长的旅程中学习编程。我知道我还有更多东西需要学习,并将继续学习如何永远地学习。最重要的事情说三遍,请继续,不要放弃,不要放弃,不要放弃。

谈谈Javascript异步代码优化

Javascript代码异步执行的场景,比如ajax的调用、定时器的使用等,在这样的场景下也经常会出现这样那样匪夷所思的bug或者糟糕的代码片段,那么处理好你的Javascript异步代码成为了异步编程至关重要的前提

编程到底难在哪里?

以买苹果为例说明程序员如何解决问题。程序员需要对问题进行透彻的分析,理清其涉及的所有细节,预测可能发生的所有意外与非意外的情况,列出解决方案的所有步骤,以及对解决方案进行尽量全面的测试。而这些正是我认为编程难的地方。

Blockly - 来自Google的可视化编程工具

Google Blockly 是一款基于Web的、开源的、可视化程序编辑器。你可以通过拖拽块的形式快速构建程序,而这些所拖拽的每个块就是组成程序的基本单元。可视化编程完成

我真是受够编程了

成为伟大的程序员,需要付出许多编程之外的努力。我们的大脑是有限的,每天要应付的问题复杂到足以让人精神崩溃。当工作不顺利时,多少都会有些冒名顶替症候群的感觉。

前端的编程软件哪些比较好用?

推荐8款最好用的前端开发工具供美工或者前端开发人员使用,当然若你是NB的全栈工程师也可以下载使用。Web前端开发最常见的编程软件有以下几种: 在前端开发中,有一个非常好用的工具,Visual Studio Code,简称VS code

如何保持学习编程的动力

学编程现在看起来挺简单,因为网上有丰富的各种资源。然而当你实际去学的时候就发现,还是很难!对我来说也一样。但从某天起,我决定认认真真学编程一年。后来又过了一年,又过了一年又一年……我好像有点感悟。

编程小技巧

命名最好遵循驼峰法和下划线法,并且要清楚的表达变量的意思。相对于驼峰法而言,我更喜欢下划线法。下划线法可以更清楚的看出这个变量表示的意思。比如aBigGreenBanana和一个a_big_green_banana。

CSS并不是真正的编程语言

每隔几个月就会出现一篇文章表明:CSS并不是真正的编程语言。以编程语言的标准来说,CSS过于困难。使用这门语言会很有创造性:事实确实如此,CSS不同于传统的编程,且具有缺陷,同任何标准化编程语言相比

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!