这是我参与「第四届青训营 」笔记创作活动的第5天
写好JavaScript的一些原则:
- 各司其职(让HTML、CSS和JavaScript职能分离)
- 组件封装(好的UI组件具备正确性、扩展性、复用性)
- 过程抽象(应用函数式编程思想)
什么是过程抽象 ?
- 处理局部细节控制的一些方法
- 函数式编程思想的基础应用
在过程抽象当中我们可以把函数可以看成一个输入和输出的黑盒,在这个过程之中我们可以去做函数过程本身的一些抽象,用来实现一些通用性解决方案。
更通俗的理解我们可以将过程抽象想象成一个房间,房间里的门、窗、和房间空间本身都是数据,但当我们要开门或者开窗时的这个动作或行为本身是一个过程,也就说我们不仅将将数据进行抽象,开这个过程也是可以进行抽象的。
案例:操作次数限制
- 一些异步交互
- 一次性的HTTP请求
下面有这样一段代码,每次点击时,会有2s的延时动画随后移除该Dom
节点,但是如果用户在该节点还没有完全移除之前又点击了几次,则会报错(Dom节点不存在)。
const list = document.querySelector('ul');
const buttons = list.querySelectorAll('button');
buttons.forEach((button)=>{
button.addEventListener('click', (evt) => {
const target = evt.target;
target.parentNode.className = 'completed';
setTimeout(()=>{
list.removeChild(target.parentNode);
},2000);
})
})
原因:当我们在2s内再次点击时,DOM
元素还存在,所以还会触发定时器执行removeChild
,但是元素只能被移除一次,所以会报错。
解决方法:我们可以对这个事件的执行次数做限制,让其只在第一次触发的时候执行。这里可以抽象出一个高阶函数once
。该函数的参数为一个函数,返回值也为一个函数,在返回的函数中判断传入过来的函数是否存在,如果存在则执行该函数,然后将该函数赋值为null这样下次就不会再执行该函数了
function once(fn) {
return function(...args) {
if(fn) {
const ret = fn.apply(this, args);
fn = null;
return ret;
}
}
}
const list = document.querySelector('ul');
const buttons = list.querySelectorAll('button');
buttons.forEach((button)=>{
button.addEventListener('click', once((evt) => {
const target = evt.target;
target.parentNode.className = 'completed';
setTimeout(()=>{
list.removeChild(target.parentNode);
},2000);
}))
});
为了让 ”只执行一次“ 的需求覆盖不同的事件处理,我们将这个需求剥离出来,这个过程就称之为 过程抽象
高阶函数 :
定义:
- 以函数作为参数
- 以函数作为返回值
- 常用于作为函数装饰器
funtion HOF(fn) {
return function(...args) {
return fn.apply(this, args);
}
}
常用的高阶函数:
- Once
- Throttle 节流函数
- Debounce 防抖函数
- Consumer / 2
- Iterative
思考: 为什么要使用高阶函数?
这里又了解到一个新的概念:
纯函数
定义:如果一个函数的返回结果只依赖于它的参数,并且在执行过程里面没有副作用则称该函数为纯函数;
使用纯函数是非常可靠的,并且不会对外界产生影响,在多人开发时能够方便进行单元测试,减少系统中非纯函数的数量,从而使得系统可靠性增加。