滴答的时钟 -- 高阶函数

功能:构建一个滴答作响的闹钟。时钟需要显示小时,分钟,秒以及当地时间的日期

要求:
1、每个字段必须是双位数字,不足补上0
2、时钟必须显示每秒的变化
3、十二小时制,用 AM PM 表示上午下午

(主要体现函数式编程)
将业务逻辑分解成更小的部分或者函数。

// 可以将许多函数,合成一个更大的函数,还可以方便地修改被合称函数的顺序(解析详细在下方)
const compose = (...fns) => 
    (arg) => 
        fns.reduce(
            (composed, f) => f(composed), 
            arg
        )
    
const oneSecond = () => 1000
const getCurrentTime = () => new Date()
const clear = () => console.clear()
const log = message => console.log(message)

// 用于转换数据的函数: 将日期对象转换成方便时钟程序调用的对象(在不改变原有数据的情况下转换数据)
// 接受date对象,为时钟构造一个包含时分秒的对象
const serialzeClockTime = date => ({
    hours: date.getHours(),
    minutes: date.getMinutes(),
    seconds: date.getSeconds()
})

// 接受一个时钟对象,返回一个小时被转换成本地时间的对象,比如:将1300 => 时钟上的1点
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"
})

// 使用高阶函数
// 获取目标函数,返回的函数将把时间发送给目标(这里的目标是console.log)
const display = target => time => target(time)

// 获取模版字符串,对时钟时间进行响应的格式化,此处使用模版hh:mm:ss
const formarClock = format => 
    time => 
        format.replace('hh', time.hours)
              .replace('mm', time.minutes)
              .replace('ss', time.seconds)
              .replace('tt', time.ampm)
    

// 获取某个对象的属性键作为参数,并预先将0赋给对象的属性值,其中的数字小于10,会在该数字前面用0不足双数。
const prependZero = key => clockTime => ({
    ...clockTime,
    [key]: (clockTime[key] < 10) ?
            "0" + clockTime[key] :
            clockTime[key]
})


// 一个独立函数,会将获取时钟时间作为参数,并通过本地时间规范将时钟时间转换成本地时间
const converToCivilianTime = clockTime => 
    compose(
        appendAMPM,
        civilianHours
    )(clockTime)


// 获取本地时间,并确保时分秒是以双位格式现实的,必要情况下数字前补0
const doubleDigits = civilianTime => 
    compose(
        prependZero('hours'),
        prependZero('minutes'),
        prependZero('seconds')
    )(civilianTime)

// 设置时间间隔启动时钟程序,将会每隔一秒执行一次回调程序,回调函数是由上面所有子程序合成的,
// 每隔一秒,控制台都会被晴空,获取当前时间,转换格式、本地化、格式化、然后显示
const startTicking = () => {
    setInterval(
        compose(
            clear,
            getCurrentTime,
            serialzeClockTime,
            converToCivilianTime,
            doubleDigits,
            formarClock('hh:mm:ss tt'),
            display(log),
        ),
        oneSecond()
    )
}

startTicking()

注意注意:大括号小括号!!

所有函数易于测试和复用。他们没有副作用,函数外部不存在全局变量。诊断问题只需按功能步骤诊断。

compose函数 - 高阶函数

const compose = (...fns) => 
    (arg) => 
        fns.reduce(
            (composed, f) => f(composed), 
            arg
        )

接收函数作为参数,并且会返回一个独立的函数,扩展运算符主要用于将这些函数参数添加到fns数组中。随后将会返回可以接受一个参数的函数,即arg。当该函数被调用时,数组fns会将作为在函数之间传递数据的起始管道。每个函数被调用后的结果累积就是上一个函数的输出结果。最后一个函数会被调用并返回了最终结果。看不懂?没关系,下面时钟例子详细解析来啦;

时钟:
1、compose 传的函数全都存在fns中,compose返回的是个函数
2、1s 后执行,此时arg 为空,reduce开始,f是clear, => clear(), 清空了控制台, composed 还是空
3、1s 后再反应,执行的是getCurrentTime, 以此类推,到serialzeClockTime, 返回的是个时钟对象
4、此时 由于reduce,结果存在了composed中,并以函数参数的形式传给了下一个函数。。。

总结:
注意点:写函数的时候注意打括号啊!跟能不能返回数据,继续执行下面的函数有关,
reduce,reduceRight 灰常好用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值