一些API的函数式编程实现
forEach的实现
js
const forEach = (array, fn) => {
let i
for (i = 0; i < array.length; i++)
fn(array[i])
}
js
const array = [1, 2, 3]
forEach(array, data => console.log(data))
forEach Object的实现
js
const forEachObject = (obj, fn) => {
for (const property in obj) {
if (obj.hasOwnProperty(property)) {
// 以key和value作为参数调用fn
fn(property, obj[property])
}
}
}
js
const object = { a: 1, b: 2 }
forEachObject(object, (k, v) => console.log(`${k}: ${v}`))
every的实现
js
const every = (arr, fn) => {
let result = true
for (let i = 0; i < arr.length; i++)
result = result && fn(arr[i])
return result
}
js
const every = (arr, fn) => {
let result = true
for (const value of arr)
result = result && fn(value)
return result
}
js
console.log(every([NaN, NaN], isNaN))
some的实现
js
const some = (arr, fn) => {
let result = false
for (const value of arr)
result = result || fn(value)
return result
}
以上的实现存在的问题
注意
- 现在的every和some都是低效的(大数组时)
- every应该在遇到第一个不匹配条件的元素时就停止遍历数组
- some函数应该在遇到第一个匹配的元素时就停止遍历数组
对象排序sortBy的实现
js
const sortBy = (property) => {
return (a, b) => {
const result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0
return result
}
}
js
const people = [
{ firstname: 'aaFirstName', lastname: 'cclastName' },
{ firstname: 'ccFirstName', lastname: 'aalastName' },
{ firstname: 'bbFirstName', lastname: 'bblastName' },
]
console.log(people.sort(sortBy('lastname')))
数组API的一些实现
map函数的实现
js
const map = (array, fn) => {
const results = []
for (const value of array)
results.push(fn(value))
return results
}
filter函数的实现
js
const filter = (array, fn) => {
const results = []
for (const value of array)
(fn(value) ? results.push(value) : undefined)
return results
}
嵌套函数连接到一个数组
js
// 将所有嵌套数组连接到一个数组中
const concatAll = (array, fn) => {
const results = []
for (const value of array)
results.push.apply(results, value)
return results
}
合并两个给定的数组
js
const zip = (leftArr, rightArr, fn) => {
let index
const results = []
for (index = 0; index < Math.min(leftArr.length, rightArr.length); i++)
results.push(fn(leftArr[index], rightArr[index]))
return results
}
reduce的实现
js
// reduce函数的第一个实现
const reduce1 = (array, fn) => {
let accumlator = 0
for (const value of array)
accumlator = fn(accumlator, value)
return [accumlator]
}
js
// reduce函数得最终实现
const reduce = (array, fn, initialValue) => {
let accumlator
if (initialValue !== undefined)
accumlator = initialValue
else
accumlator = array[0]
if (initialValue === undefined) {
for (let i = 1; i < array.length; i++)
accumlator = fn(accumlator, array[i])
}
else {
for (const value of array)
accumlator = fn(accumlator, value)
}
return [accumlator]
}
一些函数式编程的'子'函数
日志函数
js
const loggerHelper = (mode, initialMessage, errorMessage, lineNo) => {
if (mode === 'DEBUG')
console.debug(initialMessage, `${errorMessage}at line: ${lineNo}`)
else if (mode === 'ERROR')
console.error(initialMessage, `${errorMessage}at line: ${lineNo}`)
else if (mode === 'WARN')
console.warn(initialMessage, `${errorMessage}at line: ${lineNo}`)
else
throw 'Wrong mode'
}
柯里化
js
const curry = (fn) => {
if (typeof fn !== 'function')
throw new Error('NO function provided')
return function curriedFn(...args) {
if (args.length < fn.length) {
return function () {
return curriedFn.apply(null, args.concat([].slice.call(arguments)))
}
}
return fn.apply(null, args)
}
}
组合函数
js
const compose = (...fns) =>
value =>
reduce(fns.reverse(), (acc, fn) => fn(acc), value)
管道函数
js
const pipe = (...fns) =>
value =>
reduce(fns, (acc, fn) => fn(acc), value)
打印偶数
js
const unless = (predicate, fn) => {
if (!predicate)
fn()
}
// 打印数组中的偶数
forEach([1, 2, 3, 4, 5, 6, 7], (number) => {
unless(number % 2, () => {
console.log(number, 'is even')
})
})
const times = (times, fn) => {
for (let i = 0; i < times; i++) fn(i)
}
// 打印1-100中的偶数
times(100, (n) => {
unless(n % 2, () => {
console.log(n, 'is even')
})
})