写在以前,这些内容参考自O`REILLY系列图书《React学习手册》git
在React中,UI是用纯函数表示的,而且在构造DOM时,是以声明式(与此相对的,是命令式)的方式。而声明式的编程是函数式编程更广义的一部分。因此,先熟悉函数式的编程,颇有必要。es6
结合了以下所述,我发现了es6中数组的新语法, 像
map
,filter
,reduce
这些,都知足了不可变性,数据转换,纯函数,高阶函数等要点,很精髓。编程
好比,在原有对象上添加属性,而不影响原对象数组
let person = {
name: 'Beckham',
age: 33
}
let player = (person, sex) => ({
...person,
sex
})
console.log(person)
console.log(player(person, 'male'))
复制代码
结果只依赖输入参数浏览器
因此,
map
,filter
,reduce
这些函数都是必不可少的。bash
对象转为数组数据结构
let country = {
"beijing": 10,
"shanghai": 6,
"shenzhen": 9
}
let obj = Object.keys(country).map(key =>
({
name: key,
value: country[key]
})
)
console.log(obj)
复制代码
数组中,寻找最大值app
let ages = [11,66,33,22,11,55]
let maxAge = ages.reduce((max, age) => {
if (max > age) {
return max
} else {
return age
}
}, 0)
console.log(maxAge)
复制代码
数组去重,思路:有的话不变,没有的话添加。函数式编程
let colors = ['red','green','blue','red','green','blue']
const distinctColor = colors.reduce((distinct, color) => (
(distinct.indexOf(color) !== -1) ? distinct : [...distinct, color]
),
[]
)
console.log(distinctColor)
复制代码
因此,数组的
map
,filter
,reduce
都是高阶函数函数
打印输出10~0
let countDown = (count, fn) => {
fn(count)
return (count > 0) ? countDown(count-1, fn) : count
}
countDown(10, count => console.log(count))
复制代码
倒计时输出10~0
let countDown = (count, fn, delay = 1000) => {
fn(count)
return (count > 0) ? setTimeout(() => countDown(count-1, fn), delay) : count
}
countDown(10, count => console.log(count))
复制代码
链式调用,就是合成技术之一
let template = 'hh:mm:ss tt'
let clockTime = template.replace('hh','09')
.replace('mm','06')
.replace('ss', '52')
.replace('tt', 'PM')
console.log(clockTime) // 09:06:52 PM
复制代码
git图的缘由,时间看起来加速了。实际运行代码显示是正确的。
![]()
// 计时器时间
const oneSecond = () => 1000
// 获取当前时间
const getCurrentTime = () => new Date()
// 清除控制台输出
const clear = () => console.clear()
// 控制台打印内容
const log = message => console.log(message)
// 构造一个时钟对象,包含时分秒
const abstractClockTime = date =>
({
hours: date.getHours(),
minutes: date.getMinutes(),
seconds: date.getSeconds()
})
// 接收一个时钟对象,
// 该方法用于指定12小时制
const civilianHours = clockTime =>
({
...clockTime,
hours: (clockTime.hours > 12) ? clockTime.hours - 12 : clockTime.hours
})
// 接收一个时钟对象
// 该方法用于,为时钟对象添加一个属性,用于表示am 或 pm
const appendAMPM = clockTime =>
({
...clockTime,
ampm: (clockTime.hours >= 12) ? "PM" : "AM"
})
/*
* @target 目标函数(本例中就是log函数)
* @time 时钟对象
* 返回的函数,会将时间发送给目标函数
* */
const display = target => time => target(time)
/*
* @format 模板字符串 "hh:mm:ss:tt"
* @time 时钟对象
* 返回的函数,将时间进行格式化
* */
const formatClock = format =>
time =>
format.replace("hh", time.hours)
.replace("mm", time.minutes)
.replace("ss", time.seconds)
.replace("tt", time.ampm)
/*
* @key 时钟对象的属性
* @clockTime 时钟对象
* 返回的函数,将时钟对象的属性,包括时分秒,当<10时,加0
* */
const prependZero = key => clockTime =>
({
...clockTime,
[key]: (clockTime[key] < 10) ? "0" + clockTime[key] : clockTime[key]
})
/*
* 接收参数为多个函数,返回一个独立的函数
* compose函数被调用,返回的独立函数进行调用时,若是不传参,
* 就以arg做为reduce的起始值,arg在使用时是undefined,
* 而一个函数在定义时,若是没有设置形参,该函数在调用时,传递的参数无效。
* 在这个栗子中,...fns为多个函数组成的数组。
*
* 也就是说,arg做为第一个函数的参数,若是该函数定义时没有指定形参,arg将被忽略,
* 第一个函数执行的结果,做为第二个函数执行的参数,依次类推。
* */
const compose = (...fns) =>
(arg) =>
fns.reduce(
(composed, f) => f(composed),
arg
)
const convertToCivilianTime = clockTime =>
compose(
appendAMPM,
civilianHours
)(clockTime)
const doubleDigits = civilianTime =>
compose(
prependZero("hours"),
prependZero("minutes"),
prependZero("seconds")
)(civilianTime)
/*
* compose已经被调用了,以后每隔1s,调用一次compose的执行结果
* 注意参与合成的函数的顺序。
*
* 清除打印台,获取时间,构造时钟对象,添加am或pm,12小时制,加0,格式化时分秒,发送给打印函数
* */
const startTicking = () =>
setInterval(
compose(
clear,
getCurrentTime,
abstractClockTime,
convertToCivilianTime,
doubleDigits,
formatClock("hh:mm:ss tt"),
display(log)
),
oneSecond()
)
startTicking()
复制代码