寫在以前,這些內容參考自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()
複製代碼