一、简介

在JavaScript中,函数就是第一类公民,它可以像字符串、数字等变量一样,使用var修饰并作为数据使用。它可以作为数值、可以作为参数、还可以作为返回结果。可以说JavaScript就是函数式编程。ES6新语言特性中,箭头函数、扩展运算符会极大地帮助开发者利用函数式编程技术进行开发。

 //定义一个箭头函数
var print = (message) => console.log(message)

1、函数作为数值使用

 //将函数作为数值使用
const array = ["XYQ",print]
console.log(array) //["XYQ", function] (2)

2、函数作为参数使用

 //将函数作为参数使用
//定义一个函数lg,它接收一个参数logger函数,lg的函数体内部会执行这个参数logger函数
//由于传入的print函数可以接收一个参数,所以logger函数在执行时,默认传入了一个字符串
const lg = logger => logger("I Am XYQ")
lg(print) //I Am XYQ

3、函数作为返回值使用

 //将函数作为返回值使用
//定一个函数fcVale,它接收一个logger函数,同时它的返回值为新的函数,新的函数可以传入
//一个变量进行打印。最终,用函数fcVale创建一个函数fc,并给fc函数传入字符串进行调用
// var fcVale = function (logger) {
// return (message) => logger(message.toUpperCase())
// }
const fcVale = logger => message => logger(message.toUpperCase()) //高阶函数, 函数既可以接收函数参数,也可以作为其他函数返回值
const fc = fcVale(print)
fc("i am xyq") //I AM XYQ

二、风格

在JavaScript开发中,对于函数的编程分为两种风格,分别是命令式和声明式,其中函数式编程就是声明式的一部分。所谓命令式,就是更加重视函数为达到目标的执行过程而不是结果,也即重执行轻结果。而声明式,则恰恰相反,对执行结果的描述远胜于执行过程,声明式的函数很容易理解它的用途是什么,至于具体的执行细节则被隐藏了。在JavaScript中,声明式函数的编程使用及其广泛。

 //定义一个字符串变量
var userString = "My Name is XYQ"

1、命令式

 //命令式:遍历字符串,将字符串的空格全部用下划线替换 【开发者必须看完这个代码快才能知道函数的作用是替换功能】
var temp = ""
for (var i=0; i<userString.length; i++){
if (userString[i] === " "){
temp += "_"
} else {
temp += userString[i]
}
}
console.log(temp) //My_Name_is_XYQ

2、声明式

 //声明式:使用正则表达式,将字符串的空格全部用下划线替换 【开发者看到replace就基本知道函数的用途就是替换功能】
const user_string = userString.replace(/ /g,"_")
console.log(user_string) //My_Name_is_XYQ

三、概念

函数式编程是JavaScript中的核心功能,它的核心概念一共有四种,分别是不可变性、纯函数、数据转换、高阶函数以及递归。

1、不可变性,说的是在函数式编程中,数据是不可以改变的,他们永远无法修改,实现不可变的工作机制就是对原生数据进行拷贝编辑,然后取代使用。

<script type="text/javascript">

//定义一个person对象
var person = {
name: "XYQ",
age: 25,
sex: "male"
} //方法一:通过Obejct.assign方法拷贝机制,创建一个空白对象,并将当前对象拷贝到空白对象上,接着重写对象值
var copyPerson = function (person, name) {
return Object.assign({}, person, {name:name}) // {} 为一个空白对象, person拷贝到{}上,重写name值
}
var newPerson = copyPerson(person,"YPX")
console.log(newPerson.name) //YPX
console.log(person.name) //XYQ,可以看到原对象没有发生改变 //方法二:通过扩展运算符特性对对象进行拷贝
const copyPerson2 = (person, name) => ({
...person,
name
})
var newPerson2 = copyPerson(person,"YPX")
console.log(newPerson2.name) //YPX
console.log(person.name) //XYQ,可以看到原对象没有发生改变 //---------------------------------------------------------------------------------// //定义一个数组对象
var persons = [
{name:"XYQ"},
{name:"YPX"}
] //方法一:使用数组的Array.concat方式将数组串联起来,生成一个新的对象并添加原生数组的副本上,不可以用Array.push这个可变函数
const addPerson = (name, persons) => persons.concat({name})
var newPersons = addPerson("HXF", persons)
console.log(newPersons) //[{name: "XYQ"}, {name: "YPX"}, {name: "HXF"}] (3)
console.log(persons) //[{name: "XYQ"}, {name: "YPX"}] (2),可以看到原数组没有发生改变 //方式二:使用扩展运算法特性对数组进行拷贝
const addPerson2 = (name, persons) => [...persons, {name}]
var newPersons2 = addPerson2("HXF", persons)
console.log(newPersons2) //[{name: "XYQ"}, {name: "YPX"}, {name: "HXF"}] (3)
console.log(persons) //[{name: "XYQ"}, {name: "YPX"}] (2),可以看到原数组没有发生改变

</script>

2、纯函数,是一个返回结果只依赖输入参数的函数,它至少需要接收一个参数并且总是返回一个值或者其他函数,它把参数当做不可变数据使用,不做任何修改。

纯函数特点:
1、函数应该至少接收一个参数;
2、函数应该返回一个值或者其他函数;
3、函数不应该修改或者影响任何传给它的参数
<script type="text/javascript">

  //定义一个person对象
var person = {
name: "XYQ",
age: 25,
sex: "male"
} //创建一个纯函数,返回值是根据参数preson生成的一个新的person,它没有改变参数person,更改的返回的新的person。
const updatePerson = person => ({
...person,
name:"YPX",
sex:"feMale"
}) //打印
var newPerson = updatePerson(person)
console.log(newPerson) // {name: "YPX", age: 25, sex: "feMale"}
console.log(person) // {name: "XYQ", age: 25, sex: "male"}, 原对象person没有发生改变 </script>

3、数据转换,函数式编程中由于数据的不可变性,它会将一种数据转换成另一种数据,使用函数生成转换后的副本进行状态的转换。

 //定义一个city数组
const cities = ["BeiJing","ChongQing","ChongDu"] //使用系统函数Array.join()将数组用分隔符连接成字符串
var cityString = cities.join(",")
console.log(cityString) // BeiJing,ChongQing,ChongDu
console.log(cities) // ["BeiJing", "ChongQing", "ChongDu"] (5) //使用系统函数Array.filter()进行谓词过滤,这个谓词始终是一个返回布尔值的函数
//会访问数组每一个元素,匹配C开头的城市,如果返回true,则将其添加到新的数组中
const newCities = cities.filter(city => city[0] === "C")
console.log(newCities) // ["ChongQing", "ChongDu"] (2)
console.log(cities) // ["BeiJing", "ChongQing", "ChongDu"] (5) //仍然使用系统函数Array.filter(),代替Array.pop()和Array.splice()函数删除元素。因为后面的两个方法是可变的。
const deleteCity = (deletedCity, cities) => cities.filter(city => city !== deletedCity)
const newCities2 = deleteCity("BeiJing", cities)
console.log(newCities2) // [ "ChongQing", "ChongDu"] (4)
console.log(cities) // ["BeiJing","ChongQing", "ChongDu"] (5) //使用系统函数Array.map(),参数也是一个函数,在函数在访问数组中每一个元素时会执行
const newCities3 = cities.map(city => `${city} China`)
console.log(newCities3) // ["BeiJing China","ChongQing China", "ChongDu China"] (5)
console.log(cities) //["BeiJing", "ChongQing", "ChongDu"] (5) // 仍然使用系统函数Array.map(),她还可以构造任意对象、数值、数组、函数等
// 1、将数组转对象
let objectCities = cities.map(city => ({cityName : city}))
console.log(objectCities) // [{cityName: "BeiJing"}, {cityName: "ChongQing"}, {cityName: "ChongDu"}] (3)
console.log(cities) // ["BeiJing", "ChongQing", "ChongDu"] (3) // 2、修改对象元素
const updateCityName = (originCityName, cityName, cities) =>
(cities.map(city => (city.cityName === originCityName) ? ({...city, cityName}) : city))
const newObjectCities = updateCityName("BeiJing","TianJin",objectCities)
console.log(objectCities) //[{cityName: "BeiJing"}, {cityName: "ChongQing"}, {cityName: "ChongDu"}] (3)
console.log(newObjectCities) //[{cityName: "TianJin"}, {cityName: "ChongQing"}, {cityName: "ChongDu"}] (3) // 3、将对象转数组(配合Object.key函数使用)
//定义一个city对象
const cityObject = {"BeiJing":"China","NewYork":"USA"}
const cityObjects = Object.keys(cityObject).map(key =>
({cityName: key, country: cityObject[key]})
)
console.log(cityObject) //{BeiJing: "China", NewYork: "USA"}
console.log(cityObjects)//[{cityName: "BeiJing", country: "China"}, {cityName: "NewYork", country: "USA"}](2) // 系统函数Array.reduce()和rArray.reduceRight()可以用来将数组转成任意值,比如数字、字符串、布尔值、对象甚至函数
// Array.reduce()函数, 从数组头部开始处理元素 ; Array.reduceRight()函数,从数组尾部 开始处理元素
// 求最值
const nums = [10,5,30,24,78,60,100]
const max = nums.reduce((max, num) => (num > max) ? num : max)
const min = nums.reduce((min, num) => (num < min) ? num : min)
console.log(max) //
console.log(min) // // 去重,items为新的空数组
const names = ["XYQ","YPX","XXF","XYQ","XYQ"]
const deletedNames = names.reduce((items, name)=> items.indexOf(name) !== -1 ? items : [...items,name], [])
console.log(names) //["XYQ", "YPX", "XXF", "XYQ", "XYQ"] (5)
console.log(deletedNames) //["XYQ", "YPX", "XXF"] (3)

4、高阶函数,是可以操作其他函数的函数,它们可以将函数当做参数传递,也可以返回一个函数,或者二者兼有之。柯里化就是典型的应用。

 //定义高阶函数,把函数当做参数
const printer = () => console.log("---printer---")
const logger = () => console.log("---logger---")
const show = (selectPrint, printer, logger) => (selectPrint) ? printer() : logger() //调用高阶函数
show(true,printer,logger) //---printer---
show(false,printer,logger) //---logger--- //定义高阶函数,把函数当做返回值
const log = (message) =>( () => console.log(message) )
const logFunction = log("I Am XYQ") //调用高阶函数
logFunction() //I Am XYQ

5、递归,它是用户创建的函数调用自身的一种技术方案,在开发中遇到循环时,通过递归可以极其精简的缩短代码量,是一种优势替代方案。

 //定义一个倒序遍历的函数
const countDown = (number, log) => {
log(number)
return (number > 0) ? countDown(number-1, log) : number
} //调用递归函数
const log = (number) => console.log(number)
countDown(5,log)// 5 4 3 2 1 0

、链式

函数式编程是将具体的业务逻辑拆分成一个个小型的简单的纯函数,方便进行功能聚焦,最终,开发者通过串联或者并联的方式将这些小型函数合成在一起进行调用即可。这个合成的过程其实就是链式调用。如之前介绍的Promise对象的应用。

 //使用系统函数replace实现链式调用
const formmater = "hh:mm:ss tt"
const currentTime = formmater.replace("hh", "22").replace("mm","07").replace("ss","00").replace("tt","PM")
console.log(currentTime) //22:07:00 PM

JavaScript:了解一下函数式编程的更多相关文章

  1. javascript - Underscore 与 函数式编程

    <Javascript函数式编程 PDF> # csdn下载地址http://download.csdn.net/detail/tssxm/9713727 Underscore # git ...

  2. 给 JavaScript 开发者讲讲函数式编程

    本文译自:Functional Programming for JavaScript People 和大多数人一样,我在几个月前听到了很多关于函数式编程的东西,不过并没有更深入的了解.于我而言,可能只 ...

  3. 通过代数,数字,欧几里得平面和分形讨论JavaScript中的函数式编程

    本文是对函数式编程范式的系列文章从而拉开了与以下延续一个. 介绍 在JavaScript中,函数只是对象.因此,可以构造函数,作为参数传递,从函数返回或分配给变量.因此,JavaScript具有一流的 ...

  4. JavaScript系列:函数式编程(开篇)

    前言: 上一篇介绍了 函数回调,高阶函数以及函数柯里化等高级函数应用,同时,因为正在学习JavaScript·函数式编程,想整理一下函数式编程中,对于我们日常比较有用的部分. 为什么函数式编程很重要? ...

  5. [置顶] Ruby,Scala和JavaScript中的函数式编程(一)

    函数式编程(英语:Functional programming)或者函数程序设计,又称泛函编程,是一种编程范型,它将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象.函数编程语言最重要的 ...

  6. 翻译连载 | 第 11 章:融会贯通 -《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

    原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...

  7. 快速入门函数式编程——以Javascript为例

    函数式编程是在不改变状态和数据的情况下使用表达式和函数来编写程序的一种编程范式.通过遵守这种范式,我们能够编写更清晰易懂.更能抵御bug的代码.这是通过避免使用流控制语句(for.while.brea ...

  8. JavaScript中函数式编程中文翻译

    JavaScript 中的函数式编程 原著由 Dan Mantyla 编写 近几年来,随着 Haskell.Scala.Clojure 等学院派原生支持函数式编程的偏门语言越来越受到关注,同时主流的 ...

  9. JavaScript与函数式编程

    JavaScript与函数式编程 绝大多数编程语言都会有函数的概念(或者说所有的?我不太确定),他们都可以做出类似的操作: function(x) { return x * x } 但是Javascr ...

  10. 拥抱函数式编程 I - 基本概念

    函数编程与命令性编程 为支持使用纯函数方法解决问题,特此创建了函数编程范例. 函数编程是一种声明性编程形式.相比之下,大多数主流语言,包括面向对象的编程 (OOP) 语言(如 C#.Visual Ba ...

随机推荐

  1. 【好书推荐】《剑指Offer》之硬技能(编程题7~11)

    本文例子完整源码地址:https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/sword <[好书推荐]& ...

  2. source insight 3 常用设置

    总结了一些source insight的一些常用设置,这些设置需求因人而异,自己用的顺手的才是最好的. 1.括号配对高亮“在前括号左侧,后括号左侧”双击鼠标左键,可以选定匹配括号和其中内容(<& ...

  3. windows系统搭建zookeeper

    安装&配置 在apache的官方网站提供了好多镜像下载地址,然后找到对应的版本 下载地址: http://mirrors.cnnic.cn/apache/zookeeper/zookeeper ...

  4. Linux中fuser命令用法详解

    描述: fuser可以显示出当前哪个程序在使用磁盘上的某个文件.挂载点.甚至网络端口,并给出程序进程的详细信息. fuser显示使用指定文件或者文件系统的进程ID. 默认情况下每个文件名后面跟一个字母 ...

  5. IT兄弟连 HTML5教程 HTML5表单 新增的表单属性1

    HTML5 Input表单为<form>和<input>标签添加了几个新属性,属性如表1. 1  autocomplete属性 autocomplete属性规定form或inp ...

  6. Oracle数据库的sql语句性能优化

    在应用系统开发初期,由于开发数据库数据比较少,对于查询sql语句,复杂试图的编写等体会不出sql语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统的响应速度就成为目 ...

  7. INT 3 中断调试处理流程

    Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html INT 3 中断调试处理流程 一.调试器如何下INT 3 断点 1 ...

  8. python爬虫网页解析之parsel模块

    08.06自我总结 python爬虫网页解析之parsel模块 一.parsel模块安装 官网链接https://pypi.org/project/parsel/1.0.2/ pip install ...

  9. JPA的entityManager的find方法与getReference方法的区别

    场景 JPA入门简介与搭建HelloWorld(附代码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103473937 ...

  10. JavaScript动态加载script方式引用百度地图API 拓展---JavaScript的Promise

    上一篇博客JavaScript动态加载script方式引用百度地图API,Uncaught ReferenceError: BMap is not defined 这篇文章中我接触到一个新的单词:Pr ...