如何写好JavaScript 2|青训营笔记

76 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的的第4天

1. 组件封装

三次重构:

  1. 插件化

  2. 模板化

  3. 抽象化(组件框架)

    • 改进空间: 是否可以父子插件分离等

2. 过程抽象

普遍应用在框架上,如react boost

常用高阶函数

1.单次执行 (once)

在页面中有一按钮,要求为其添加事件监听器:当这个按钮被点击时,

  • 在控制台打印 "hello world!" ;
  • 并要求这个动作只执行一次,若之后按钮再次被点击,打印动作也不会执行。

我们通常使用的方法是 addEventListener,并且在可选参数options中将 once 设置为 true ,意为只执行一次。

const btn = document.getElementById('btn');
document.addEventListener('click',()=>{
    console.log('hello world!');
},{once:true});

2.节流 (throttle)

以页面中的按钮为例子,我希望用户在点击这个按钮时,

  • 控制台中会打印 "hello world!" ;
  • 为按钮发挥作用添加冷却时间,如500ms。

这意味着 addEventListener 绑定的函数在执行一次后会进入500ms的冷却时间,当这一冷却时间结束后,点击按钮才能产生打印"hello world!"的效果;但下一次打印操作完成后,按钮又会再次进入冷却。 在冷却过程中,无论用户点击多少次按钮,都不会有打印的操作。

这样的限制条件称为节流(throttle) 。下面是一个针对节流的高阶函数:

function throttle(fn,time = 500){
    let timer;
    return function(...args){
        if(timer == null){
            fn.apply(this,args);
            timer = setTimeout(()=>{
                timer = null;
            },time);
        }
    }
}

对于使用高阶函数throttle()生成新函数时,传入的参数除了包含被调用的回调函数外,还需要传入一个间隔的时间time,回调函数的执行便以time为时间间隔。具体时间可由使用者指定。

3.防抖 (debounce)

页面上存在一个内容被监听的多行输入框,对于这一输入框:

  • 当输入框中的内容发生变化时,控制台实时打印输入框中的内容;
  • 但必须在用户无输入操作500ms后,才允许进行打印操作。

如果不添加 “用户无输入操作若干秒后才打印” 的限制条件,当输入框的内容稍有变化时,控制台便会马上打印;当内容变化的次数一多,控制台打印操作便会变得频繁,产生抖动。

对于一些不希望产生抖动的操作,则需要添加限制条件,称为 防抖(debounce) 。下面是一个针对防抖的高阶函数:

function debounce(fn,dur = 500){
    let timer;
    return function(...args){
        clearTimeout(timer);
        timer = setTimeout(()=>{
            fn.apply(this,args);
        },dur);
       
    }
}

参数dur等待无操作所持续(duration)的时间

每次在执行debounce()返回的新函数前,都要使用clearTimeout()方法取消setTimeout()的定时,即打断当前的等待间隔时间和执行规律,随后再重新设置一个定时器。
在新设置的定时器中,以dur为时间间隔执行回调函数。

为什么要使用高阶函数?

纯函数与非纯函数

纯函数 (pure function)

  • 对外部没有副作用
  • 效果可预期

非纯函数 (inpure function)

  • 对外部有副作用
  • 测试时要构造特定的环境、初始化和还原
  • 测试难度更大

| 非纯函数越多,可维护性就越差,所以尽量使用纯函数。 |

使用高阶函数的好处

  • 过程抽象
  • 高阶函数都是纯函数,效果可预期
  • 提升代码的可维护性