一、简介

在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. Android 程序分析环境搭建-动态分析环境搭建

    静态查看过app 的代码,但是有些app 非常复杂,页面好多,你根本找不到从何处下手.还有app 通过静态分析,发现有被加固(后续会讲如何砸壳),根本找不到,还有即便你搜索app界面上的文字,你也搜索 ...

  2. Test Case:: 12C ASM New feature (Doc ID 1571975.1)

    Test Case:: 12C ASM New feature (Doc ID 1571975.1) APPLIES TO: Oracle Database - Enterprise Edition ...

  3. git 分布式控制版本管理器(上)

    git的作用: 1.更方便的存储版本 2.恢复之前的版本 3.更方便的对比 4.协同合作 下载地址git官网: https://git-scm.com/ 可自选自己电脑的操作系统 安装: 一路next ...

  4. 无需重新安装软件,将软件从C盘移至其他盘(mklink)

    事先说明,这篇博文算是视频的文字转载版,来源为该视频的五分钟后内容→https://www.bilibili.com/video/av78397784/ 如何拯救标红的C盘[高玩] 有时候安装软件会手 ...

  5. C++继承产生的问题

    今天写代码,用到了继承,忘了将父类中的私有成员改为protected,结果一调用父类地函数后,子类中的root指针直接变为了父类中的空的root.私有成员在继承后依然会保留,占一定的内存空间,但却没有 ...

  6. UNIX系统编程知识点总结——思维导图

    根据考纲整理了一下本学期系统编程课的知识点,并且做成了思维导图便于理解和记忆 主要都是一些比较入门的知识点,UNIX博大精深,每一个知识点其实都能深挖 因为博客园不可能直接出思维导图,本文的主要内容都 ...

  7. PHP 开发工程师基础篇 - PHP 数组

    数组 (Array) 数组是 PHP 中最重要的数据类型,可以说是掌握数组,基本上 PHP 一大半问题都可以解决. PHP 数组与其他编程语言数组概念不一样.其他编程语言数组是由相同类型的元素(ele ...

  8. Git详细学习教程

    作者:gafish https://github.com/gafish/gafish.github.com Git简介 Git 是一种分布式版本控制系统,它可以不受网络连接的限制,加上其它众多优点,目 ...

  9. 基于STM32F429,Cubemx的SAI音频播放实验

    书接上文:https://www.cnblogs.com/feiniaoliangtiangao/p/11060674.html 和 https://www.cnblogs.com/feiniaoli ...

  10. 常用类-ExcelHelper

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...