函数组合
- 函数组合是一个数学概念,允许您将两个或更多个函数组合到一个新函数中。
- 功能组合的关键是具有可组合的函数,即组合的函数应该有1个输入参数和1个输出值(如果有多个参数,通过函数curry去实现)
- 示例
const compose = (...functions) => data =>
functions.reduceRight((value, func) => func(value), data)
const encodeAttribute = (x = '') =>
x.replace(/"/g, '"')
const toAttributeString = (x = {}) =>
Object.keys(x)
.map(attr => `${encodeAttribute(attr)}="${encodeAttribute(x[attr])}"`)
.join(' ')
const tagAttributes = x => (c = '') =>
`<${x.tag}${x.attr?' ':''}${toAttributeString(x.attr)}>${c}</${x.tag}>`
const tag = x =>
typeof x === 'string' ?
tagAttributes({
tag: x
}) :
tagAttributes(x)
const listGroup = tag({
tag: 'ul',
attr: {
class: 'list-group'
}
})
const listGroupItem = tag({
tag: 'li',
attr: {
class: 'list-group-item'
}
})
const listGroupItems = items =>
items.map(listGroupItem)
.join('')
listGroup()
listGroupItem('Cras justo')
listGroupItems(['Cras justo', 'Dapibus ac'])
listGroup(listGroupItems(['Cras justo', 'Dapibus ac']))
compose(listGroup, listGroupItems)(['Cras justo1', 'Dapibus ac2', 'Cras justo3', 'Dapibus ac4'])
复制代码
// 函数接收一个callback,有四个参数,
// 每次回调的各参数值请参考表格
// initialValue:作为第一次调用 //callbackfn函数的第一个参数
var arr = [0,1,2,3,4];
arr.reduceRight(function (preValue,curValue,index,array) { return preValue + curValue; }, initialValue);
复制代码
preValue | curValue | index | array | 返回值 |
---|
0 | 1 | 1 | [0,1,2,3,4] | 1 |
1 | 2 | 2 | [0,1,2,3,4] | 3 |
3 | 3 | 3 | [0,1,2,3,4] | 6 |
6 | 4 | 4 | [0,1,2,3,4] | 10 |
console.clear()
/***********************************************************
* functional.js
***********************************************************/
const compose = (...functions) => data =>
functions.reduceRight((value, func) => func(value), data)
const set = prop => obj => value =>
(obj[prop] = value, obj)
const map = f => x =>
Array.prototype.map.call(x, f)
const join = seperator => list =>
Array.prototype.join.call(list, seperator)
/***********************************************************
* dom.js
***********************************************************/
const setInnerHtml = set('innerHTML')
/***********************************************************
* html.js
***********************************************************/
const encodeAttribute = (x = '') =>
x.replace(/"/g, '"')
const toAttributeString = (x = {}) =>
compose(
join(' '),
map(attr => `${encodeAttribute(attr)}="${encodeAttribute(x[attr])}"`),
Object.keys
)(x)
const tagAttributes = x => (contents = '') =>
`<${x.tag}${x.attr?' ':''}${toAttributeString(x.attr)}>${contents}</${x.tag}>`
const tag = x =>
typeof x === 'string'
? tagAttributes({ tag: x })
: tagAttributes(x)
// list-group
const listGroupTag = tag({ tag: 'ul', attr: { class: 'list-group' }})
const listGroupItem = tag({ tag: 'li', attr: { class: 'list-group-item' }})
const listGroupItems = list =>
list.map(listGroupItem)
.join('')
const listGroup = compose(listGroupTag, listGroupItems)
// panel
const panelTag = tag({ tag: 'div', attr: { class: 'panel panel-default' }})
const panelBody = tag({ tag: 'div', attr: { class: 'panel-body' }})
const basicPanel = compose(panelTag, panelBody)
const listGroupPanel = compose(basicPanel, listGroup)
/***********************************************************
* main.js
***********************************************************/
const content = document.getElementById('content')
const main = e =>
compose(setInnerHtml(e), listGroupPanel)
const list = [
'Cras justo odio',
'Dapibus ac facilisis in',
'Morbi leo risus',
'Porta ac consectetur ac',
'Vestibulum at eros'
]
main(content)(list)
复制代码