优化JS代码的三大原则 | 青训营笔记

67 阅读4分钟

「青训营」笔记创作活动的的第4天

JS 代码优化原则 - 各司其职

1644217394.png

HTML 负责页面的框架,CSS 负责页面的展现,JavaScript 负责页面的行为。

案例:实现夜间模式的切换

版本一:JS 直接操作样式

 const btn = document.getElementById("modeBtn");
 btn.addEventListener("click", (e) => {
     const body = document.body;
     if (e.target.innerHTML === "🌞") {
         body.style.backgroundColor = "black";
         body.style.color = "white";
         e.target.innerHTML = "🌜";
     } else {
         body.style.backgroundColor = "white";
         body.style.color = "black ";
         e.target.innerHTML = "🌞";
     }
 });
复制代码

不足:

  1. 语义不清晰,难以从代码中读出功能意图
  2. 后期难以维护
  3. 违背各司其职原则,js 不应当直接操作元素的样式

版本二:JS 切换类选择器

 const btn = document.getElementById("modeBtn");
 btn.addEventListener("click", (e) => {
     const body = document.body;
     if (body.className !== "night") {
         body.className = "night";
     } else {
         body.className = "";
     }
 });
复制代码

优化:

  1. 太阳和月亮图标不是直接以文本形式写在按钮里面,而是通过::after 伪元素添加进去
  2. 通过类选择器给元素添加样式,再通过 js 控制类选择器

版本三:零 JS 代码实现

优点:

  1. 通过 label 标签绑定多选框,再通过多选框的:checked 伪类选择器控制样式的切换
  2. 零 JS 代码
  3. 易于后期维护

案例总结

  • HTML/CSS/JS 各司其责
  • 应当避免不必要的通过 JS 直接操作元素样式
  • 可以用 class 来表示状态
  • 纯展示类交互寻求零 JS 方案

JS 代码优化原则 - 组件封装

案例:实现一个轮播图

  1. 结构:HTML - 无序列表<ul>
  2. 表现:CSS
  • 绝对定位将图片重叠在同一个位置
  • 轮播图切换状态使用修饰符(modified)
  • 动画切换使用 transition
  1. 行为:JS - API 设计应保证原子操作,职责单一,满足灵活性。行为设计:
  • API (功能) 版本一
  • Event(控制流):使用自定义事件来解耦 版本二

优化:

重构 - 插件化: 解耦:

  • 控制元素抽取成插件

  • 插件与组件之间通过依赖注入方式建立联系 补充:在JS中 一个对象方法或者一个函数尽量控制在15行代码以内。
    版本三

    重构 - 模板化:更易于拓展,不需要的功能可以直接去掉而不影响其他功能
    版本四

    重构 - 组件抽象框架:将通用的组件抽象出来
    版本五

总结

组件是指Web页面上抽出来一个个包含模板(HTML)、功能(JS)、和样式(CSS)的单元;
组件设计的原则:封装性、正确性、拓展性、复用性;
实现组件的步骤:结构设计、展现效果、行为设计;
三次重构:插件化、模板化、抽象化。

JS 代码优化原则 - 过程抽象

过程抽象:

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

例子 - 操作次数限制:

假如需要对某个函数的调用次数进行限制,我们可以直接在函数内进行控制,但是如果出现了多个同样需求的函数,则未免会写很多重复的的代码,此时我们可以通过一个高阶函数完成这个功能。

 function once(fn){
     return function (...args) {
         if(fn){
             const ret = fn.apply(this, args);
             fn = null;
             return ret;
         }
     };
 }
复制代码

为了能够让“只执行一次”的需求覆盖不同的事件处理,我们可以将这个需求剥离出来。这个过程我们称为过程抽象。

高阶函数

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

高阶函数

常用的高阶函数:

为什么要使用高阶函数?

函数可以分为纯函数和非纯函数。

纯函数:在任何时候以相同的参数调用它,输出是相同的,即不依赖于外部环境。

非纯函数:非纯函数依赖外部环境(或者说是调用时机),当使用相同的参数在不同的外部环境调用时,函数输出的结果果也会不同。

因为非纯函数很难保证每次调用时都有相同的外部环境,所以使用纯函数更有助于后期的单元测试。并且使用纯函数可以使得系统更加稳定。

编程范式

  • 命令式:过程式、面向对象
  • 声明式:逻辑式、函数式

编程范式

JS 是混合的编程方式,既可以写出命令式风格的代码,也可以写出声明式风格的代码。

例子 - 切换状态

Toggle - 命令式

Toggle - 声明式

Toggle - 三态