You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
exportdefaultfunctioncompose(...funcs: Function[]){if(funcs.length===0){// infer the argument type so it is usable in inference down the linereturn<T>(arg: T) =>arg}if(funcs.length===1){returnfuncs[0]}returnfuncs.reduce((a,b)=>(...args: any)=>a(b(...args)))}
一、什么是高阶函数
1.1 一等类函数(First-class Functions)
函数也是对象。
1.2 函数式编程(Functional Programming)
JS里函数就是对象,可以实现函数式编程。
1.3 高阶函数
wiki关于高阶函数的定义:在数学和计算机科学中,高阶函数是至少满足下列一个条件的函数:
通俗点说就是高阶函数是那些操作其他函数的函数。
高阶函数就是函数式编程的实现。
1.4 内置的高阶函数
JS内置对象的好多方法都是高阶函数:
Array.prototype.map/filter/forEach/reduce/every/some/find/findIndex
;Function.prototype.bind
;二、underscore/lodash高阶函数实现分析
1. 防抖(debounce)
2. 节流(throttle)
3. 记忆(memorize)
4. 组合函数(Compose)
是什么是组合函数
函数嵌套调用扁平化处理。有点类似管道,把上一个函数处理结果作为输入传给下一个函数。
相当于嵌套调用
split(lowerCase(trim("a,B,C)))
实现-初版
Array.prototype.reduce
实现的;compose(add2, multi3)
相当于multi3(add2())
;因为上一个函数的返回值只有一个。
underscorejs实现
compose(add2, multi3)
相当于add2(multi3())
;至于执行方向选择哪种都都道理,不过还是跟明星库保持一致吧。
this
【Nice】;这样组合函数可以通过
apply
/call
方式动态修改this
调用了。lodash实现
Lodash居然没有compose函数。
实现-优化
借鉴underscore和这个博客JS高阶编程技巧--compose函数重新优化下实现:
redux compose
实现无意中看到Redux库的
compose
实现,简直简洁到爆炸:简直炸裂!相较于
underscore
的实现就少了this
透传。但提前转成了函数嵌套调用,执行的时候没有循环了。参考这个又修改了下之前的实现:
虽然提前转成嵌套调用,但是实参函数列表有一半的函数都是利用
apply
方式调用,很难说性能谁的更好。npm p-pipe
5. 柯里化(Currying)
什么是柯里化
来自wiki定义
可以
foo(3)(4)
方式调用上面的函数。不过现实中可不用受每次只能传单个参数的限制。
实现-初版
underscore实现
underscore居然没有柯里化函数。
lodash实现
6. 偏函数(Partial Function)
什么是偏函数
偏函数应用(Partial Application)是指固定一个函数的某些参数,然后产生另一个更小元的函数。
跟柯里化的区别
两者概念比较类似,但是存在区别的。
一次性给函数降维
根据调用情况逐步降维
比较有名的内置偏函数
Object.prototype.bind
。之前一直把它视为柯里化函数。实现-初版
实现上就像个简化版的
Object.prototype.bind
。这个实现存在一个问题就是只能对左边的参数依次进行固定。
underscore和lodash实现
逻辑差不多,不过增加占位符(
placeholder
)的概念,用于处理对任意位置的参数进行固化。实现-增加占位符
感觉用处不大,尽量使用
Object.prototype.bind
吧。7. 时间分片(Time Slicing)/分时函数
什么是时间分片
当一个任务(事件处理函数,回调函数)执行时间过长时,Chrome会有个warn:
根据W3C性能的介绍,超过50ms的任务就是长任务
针对超长任务有两种解决方案:
时间分片
参考了这个文章JavaScript中的时间分片(Time Slicing):
实现
delay
执行一批;yield
天生就是让出主线程执行权啊,然后在适当的时候通过生成器对象next
方法获取执行权。注意:
分片的大小要适度,不能太小,EventLoop任务调度也是要花费时间的,分片太小反而影响性能。
这个就属于分片太小了(每插入一个标签就setTimeout),估计很久还没插入100000个
li
标签。利用requestIdleCallback
优化:大概8s就搞定了。
参考
The text was updated successfully, but these errors were encountered: