Curry
函数柯里化相关方法
all
创建一个按顺序运行的函数链
链接函数将导致它们一个接一个地执行,将每个函数的输出作为下一个函数的输入传递,并在链的末尾返回最终输出。
1 2 3 4 5 6 7 8 9 10 11
| import { chain } from 'radash'
const add = (y: number) => (x: number) => x + y const mult = (y: number) => (x: number) => x * y const addFive = add(5) const double = mult(2)
const chained = chain(addFive, double)
chained(0) chained(7)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import { chain } from 'radash'
type Deity = { name: string rank: number }
const gods: Deity[] = [ { rank: 8, name: 'Ra' }, { rank: 7, name: 'Zeus' }, { rank: 9, name: 'Loki' }, ]
const getName = (god: Deity) => item.name const upperCase = (text: string) => text.toUpperCase() as Uppercase<string>
const getUpperName = chain(getName, upperCase)
getUpperName(gods[0]) gods.map(getUpperName)
|
chain 函数接受一个可变参数 funcs,这些参数是函数类型 (…args: any[]) => any,即这些函数可以接受任意数量的参数,并返回任意类型的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| export function chain<T1 extends any[], T2, T3>( f1: (...arg: T1) => T2, f2: (arg: T2) => T3 ): (...arg: T1) => T3
export function chain(...funcs: ((...args: any[]) => any)[]) { return (...args: any[]) => { return funcs.slice(1).reduce( (acc, fn) => fn(acc), funcs[0](...args) ) } }
|
compose
创建组合函数
在函数组合中,每个函数都会被赋予下一个函数作为参数,并且必须调用它才能继续执行。
1 2 3 4 5 6 7 8 9 10 11 12 13
| import { compose } from 'radash'
const useZero = (fn: any) => () => fn(0) const objectize = (fn: any) => (num: any) => fn({ num }) const increment = (fn: any) => ({ num }: any) => fn({ num: num + 1 }) const returnArg = (arg: any) => (args: any) => args[arg]
const composed = compose(useZero, objectize, increment, increment, returnArg('num'))
composed()
|
compose 函数,用于将多个函数组合成一个函数。具体来说,它接受一个或多个函数作为参数,并返回一个新的函数,这个新函数会依次调用这些函数,并将前一个函数的返回值作为后一个函数的参数。
1 2 3 4 5 6 7 8 9 10 11
| export function compose<F1Result, F1Args extends any[], F1NextArgs extends any[], LastResult>( f1: (next: (...args: F1NextArgs) => LastResult) => (...args: F1Args) => F1Result, last: (...args: F1NextArgs) => LastResult ): (...args: F1Args) => F1Result
export function compose(...funcs: ((...args: any[]) => any)[]) { return funcs.reverse().reduce((acc, fn) => fn(acc)) }
|
compose 函数在函数式编程中非常有用,特别是在需要将多个函数组合成一个函数时。例如,在处理数据流或构建复杂函数时,可以将多个简单的函数组合成一个复杂的函数,从而简化代码和提高可读性。
debounce
创建一个防抖函数. 当函数被连续调用时,只有在最后一次调用后的指定延迟时间过去后,函数才会被执行。如果在这段时间内函数再次被调用,则重新计时。
Debounce 接受一个带有延迟的选项对象和一个在调用时调用的源函数。当调用返回的函数时,它只会在延迟毫秒时间过去后调用源函数。不会导致调用源的调用会重置延迟,从而推迟下一次调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import { debounce } from 'radash'
const makeSearchRequest = event => { api.movies.search(event.target.value) }
input.addEventListener('change', debounce({ delay: 100 }, makeSearchRequest))
const debounced = debounce({ delay: 100 }, api.feed.refresh)
debounced.cancel()
debounced.flush(event)
debounced.isPending()
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| export type DebounceFunction<TArgs extends any[]> = { (...args: TArgs): void
cancel(): void
isPending(): boolean
flush(...args: TArgs): void } export const debounce = <TArgs extends any[]>( { delay }: { delay: number }, func: (...args: TArgs) => any ) => { let timer: NodeJS.Timeout | undefined = undefined let active = true
const debounced: DebounceFunction<TArgs> = (...args: TArgs) => { if (active) { clearTimeout(timer) timer = setTimeout(() => { active && func(...args) timer = undefined }, delay) } else { func(...args) } } debounced.isPending = () => { return timer !== undefined } debounced.cancel = () => { active = false } debounced.flush = (...args: TArgs) => func(...args)
return debounced }
|
throttle
创建一个节流函数
Throttle 接受一个带有间隔的选项对象和一个在调用时调用的源函数。当调用返回的函数时,只有在经过了间隔毫秒的时间后,它才会调用源函数。否则,它将忽略该调用。
1 2 3 4 5 6 7
| import { throttle } from 'radash'
const onMouseMove = () => { rerender() }
addEventListener('mousemove', throttle({ interval: 200 }, onMouseMove))
|
这段代码实现了一个简单的缓存(memoization)功能,用于优化函数的执行。它通过缓存函数的返回值来避免重复计算,从而提高性能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| export type ThrottledFunction<TArgs extends any[]> = { (...args: TArgs): void isThrottled(): boolean }
export const throttle = <TArgs extends any[]>( { interval }: { interval: number }, func: (...args: TArgs) => any ) => { let ready = true let timer: NodeJS.Timeout | undefined = undefined
const throttled: ThrottledFunction<TArgs> = (...args: TArgs) => { if (!ready) return
func(...args) ready = false timer = setTimeout(() => { ready = true timer = undefined }, interval) } throttled.isThrottled = () => { return timer !== undefined } return throttled }
|
partial
partial 函数可以用于创建一个新函数,这个新函数在调用时只需要提供原始函数的一部分参数。这在需要多次调用同一个函数,但参数大部分相同的情况下非常有用
1 2 3 4 5 6
| import { partial } from 'radash'
const add = (a: number, b: number) => a + b const addFive = partial(add, 5)
addFive(2)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
type RemoveItemsInFront< TItems extends any[], TItemsToRemove extends any[] > = TItems extends [...TItemsToRemove, ...infer TRest] ? TRest : TItems
export const partial = <T extends any[], TA extends Partial<T>, R>( fn: (...args: T) => R, ...args: TA ) => { return (...rest: RemoveItemsInFront<T, TA>) => fn(...([...args, ...rest] as T)) }
|
partob
现代 JavaScript 解构意味着许多开发人员、库和框架都选择采用包含参数的单个对象的一元函数。
_.partob
函数让您可以分解这些一元函数。
1 2 3 4 5 6 7
| import { partob } from 'radash'
const add = (props: { a: number; b: number }) => props.a + props.b
const addFive = partob(add, { a: 5 })
addFive({ b: 2 })
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| export const partob = <T, K, PartialArgs extends Partial<T>>( fn: (args: T) => K, argobj: PartialArgs ) => { return (restobj: Omit<T, keyof PartialArgs>): K => fn({ ...(argobj as Partial<T>), ...(restobj as Partial<T>), } as T) }
|
proxied
创建动态代理对象
Javascript 的 Proxy 对象功能强大,这里为定制用法。 _.proxied
函数为您创建代理,并在调用代理上的函数或访问属性时处理对处理程序的回调。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import { proxied } from 'radash'
type Property = 'name' | 'size' | 'getLocation'
const person = proxied((prop: Property) => { switch (prop) { case 'name': return 'Joe' case 'size': return 20 case 'getLocation' return () => 'here' } })
person.name person.size person.getLocation()
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| export const proxied = <T, K>( handler: (propertyName: T) => K ): Record<string, K> => { return new Proxy( {}, { get: (target, propertyName: any) => handler(propertyName), } ) }
|
这个函数可以用于创建一个动态的属性访问系统,其中属性的值是根据属性名动态计算的。这在需要根据属性名生成不同值的场景中非常有用,比如根据属性名从对象中获取值、根据属性名生成计算结果等。