如何写好 JavaScript(三) | 青训营笔记

72 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第 6 天。(第五篇笔记)

本篇笔记再次仍然延续上一节的内容,继续为「如何写好 JavaScript 」,从「过程抽象」的角度出发。

过程抽象

过程抽象是:

  • 用来处理局部细节控制的一些方法
  • 函数式编程思想的基础应用

image.png

过程抽象的理解: 可以将函数看作是一个输入和输出的黑盒,在黑盒(过程)之中可以做函数过程本身的一些抽象,实现一些通用型的方案。

将过程抽象想象成一个房间,房间中的门、窗和房间空间本身都是数据,要完成「开门」和「关门」的动作或者行为本身是一个过程,也就是说不仅要将数据进行抽象,「开门」这个过程也可以抽象。

🌰 例子 / 操作次数的限制:

codepen button list (codepen.io)

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 节点不存在)。

原因:在 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);
    })
  );
});

在这个例子中,只执行一次需要覆盖不同的事件处理,过程抽象就是将 只执行一次 的需求抽离出来。

高阶函数

高阶函数的定义:

  • 以函数为参数;
  • 以函数作为返回值;
  • 常用于函数装饰器;

🌰 例子:

function HOF(fn) {
  return function(...args) {
    return fn.apply(this, args)
  }
}

常用的高阶函数有:

  • once 只执行一次函数
  • throttle 节流函数
  • debounce 防抖函数
  • consumer
  • iterative

为什么要使用高阶函数(如何理解高阶函数 - 掘金 (juejin.cn)

高阶函数把 函数当作变量

纯函数

纯函数的定义:如果一个函数的返回结果只依赖他的参数,并且执行过程没有副作用则称为纯函数。

使用纯函数非常可靠,并且不会对外界产生影响。再多人开发中能够方便进行单元测试。减少系统中非纯函数的属性,从而使得系统可靠性增加。

总结

到目前为止(「如何写好 JavaScript」这个主题),已经接触了写好 JavaScript 的三个原则:

  • 各司其职
  • 组件封装(封装性、正确性、拓展性、复用性)
  • 过程抽象(函数式编程思想)