如何写好JavaScript 笔记 | 青训营

48 阅读7分钟

前端爱好者和真正的前端工程师之间的差距之一就体现在对JavaScript代码的运用,如何才能避免写出又臭又长,只有自己看得懂的代码?老师提出了JS好代码的三大原则,让我们一起来看:

JavaScript 编码原则之各司其责

——让HTML、CSS和JavaScript职能分离。

以实现深夜食堂网页深、浅色模式为例

image.png

版本一:

image.png

缺点在于在JavaScript中写CSS,且代码重复冗长。修改思路在于把JavaScript和CSS代码分开,各司其责。

版本二:

image.png

这下代码清晰多了!思考一下面临零JS需求时怎么办吧。

版本三:

image.png

技巧在于隐藏一个checkbox,并把checkbox的id与太阳月亮图标的for捆绑。

小小总结一下深夜食堂:

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

JavaScript 编码原则之组件分装

——好的UI组件具备正确性、扩展性,复用性。

以实现轮播图为例:

结构设计(HTML)

轮播图是一个典型的列表结构,我们可以使用无序列表<ul>来实现。

image.png

展现效果(CSS)

  • 使用CSS绝对定位将图片重叠在同一个位置
  • 轮播图切换的状态使用修饰符(modifier)
  • 轮播图的切换动画使用CSS transition

image.png

行为设计(JS API EVENT)

API设计应保证原子操作,职责单一,满足灵活性。

image.png

EVENT控制流使用自定义事件来解耦

image.png

三个重构(优化)方法:

image.png 插件化是指将应用程序的功能或特性划分为独立的模块,这些模块可以动态地加载或卸载,从而增加或改变应用程序的功能。插件化使得应用程序的功能能够根据需要进行灵活扩展,而不需要对应用程序的核心代码进行大规模修改。插件通常是独立的代码单元,可以以外部模块的形式添加到应用程序中,允许开发者在不影响应用程序稳定性的前提下进行功能定制和扩展。

image.png 模版化是指在应用程序开发中使用模板来生成动态内容的技术。模板是预定义的文本或代码片段,其中包含占位符或变量,用于将实际数据动态填充进去。模版化技术常用于生成网页、电子邮件、报告等内容。通过使用模板,开发者可以将展示层和业务逻辑分离,从而使得代码更易于维护和修改。模板引擎是一种工具,用于处理模板并将其与数据结合,生成最终的输出。

image.png 在面向对象编程中,抽象化是通过抽象类和接口来定义通用的行为和结构,从而让子类来实现具体的功能。

JavaScript 编码原则之过程抽象

——应用函数式编程思想。

过程抽象是函数式编程思想的基础应用,用来处理局部细节控制的一些方法。

image.png

image.png

image.png

1.节流Throttle是一种限制函数执行频率的技术。当一个事件被频繁触发时,节流会确保在一定时间间隔内只执行一次该事件的处理函数。这可以防止在短时间内连续执行同一个事件的处理函数,从而减少频繁触发事件造成的性能浪费。

应用场景:

  • 滚动事件:当用户滚动页面时,频繁触发滚动事件处理函数可能导致页面卡顿,使用节流可以减少事件的触发次数。
  • 表单输入验证:当用户在输入框中快速输入时,节流可以减少频繁的输入验证请求。

2.防抖Debounce是一种限制函数执行频率的技术。当一个事件被触发时,防抖会等待一段时间,在这段时间内如果该事件被再次触发,则重新计时。只有在等待时间内没有再次触发该事件时,才会执行事件的处理函数。这可以确保在事件连续触发的情况下,只执行最后一次触发时的事件处理函数。

应用场景:

  • 搜索框输入:当用户在搜索框中输入内容时,频繁触发搜索请求会增加服务器负担,使用防抖可以确保用户停止输入一段时间后才进行搜索请求。
  • 窗口大小调整:当用户调整浏览器窗口大小时,频繁触发窗口调整事件可能导致页面重新渲染多次,使用防抖可以避免过多的重绘操作。

3.迭代Iterative是一种重复执行某个操作或处理序列的过程。在编程中,迭代通常用于遍历数据集合(如数组、列表、集合等)中的每个元素,以便进行处理、访问或转换操作。

  • 课程中的例子是批量修改表单文字颜色
一些知识点

在编程中,函数可以分为两种类型:纯函数(Pure Function)和非纯函数(Impure Function)。非纯函数是指在执行过程中可能会对函数外部的状态进行修改或产生副作用的函数。

特点和行为:

  1. 修改外部状态:非纯函数在执行过程中可能会修改外部的变量或对象,导致外部状态发生变化。
  2. 副作用:非纯函数可能会产生除了返回结果之外的其他影响,称为副作用。这些副作用可能包括但不限于:修改全局变量、修改传入的对象、修改文件、网络请求等。
  3. 不可预测性:由于非纯函数的执行可能依赖于外部状态,所以它的行为在相同输入的情况下不一定总是相同的,这会增加代码的不可预测性和调试难度。

高阶函数属于纯函数,纯函数相比于非纯函数更容易测试


闭包是一种在编程中常见的概念,它是指函数可以访问并操作其词法作用域外部的变量。简单来说,当一个函数在定义时,内部引用了其外部的变量,即使这个函数被调用执行时,这些外部变量依然可以被访问,这种函数和其相关引用的变量就形成了一个闭包。

闭包由两部分组成:

  1. 函数(Function):闭包是一个函数,其中包含对词法作用域外部变量的引用。
  2. 词法环境(Lexical Environment):闭包创建时,会将其所在的词法环境(包含了函数定义时的所有变量)和函数绑定在一起,使得函数可以在执行时访问这些外部变量。

简单示例来解释闭包:

function outerFunction() {
  let outerVariable = 10;

  function innerFunction() {
    console.log(outerVariable); // 在内部函数中访问外部变量
  }

  return innerFunction; // 返回内部函数,形成闭包
}

const closureFunction = outerFunction();
closureFunction(); // 输出 10,因为闭包中的函数仍然可以访问外部的 outerVariable

在上面的示例中,innerFunction是一个闭包,它被返回并赋值给变量closureFunction。尽管outerFunction执行完毕后,其内部变量outerVariable本来应该被销毁,但由于innerFunction形成了闭包,它仍然可以访问并使用outerVariable的值。

闭包有一些应用场景,例如:

  1. 封装:通过闭包,可以实现私有变量,隐藏实现细节,暴露接口。
  2. 延迟执行:可以用闭包实现延迟执行,例如使用闭包实现节流和防抖功能。
  3. 保持状态:在某些情况下,闭包可以用于保持函数执行时的状态,避免全局变量的使用。

需要注意的是,闭包可能导致内存泄漏问题,因为闭包会一直引用外部的变量,导致这些变量无法被垃圾回收。因此,在使用闭包时,需要注意避免过度使用,确保正确释放不再需要的闭包。


image.png

命令式更强调“怎么做”,声明式更强调“做什么”。