写好JS|青训营笔记

写好JS|青训营笔记

我的图图呢 1,519 2022-08-25

如何写好JavaScript

写好JS的一些原则:各司其职、组件封装、过程抽象

各司其责

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

组件封装

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

  • 结构设计:HTML
  • 展现效果:CSS
  • 行为设计:JS
    • API(功能),API 设计应保证原子操作,职责单一,满足灵活性。
    • Event(控制流),使用自定义事件来解耦。
  • 插件化重构,即解耦
    • 将控制元素抽取成插件
    • 插件与组件之间通过依赖注入方式建立联系
  • 模板化重构
    • 将HTML模板化,更易于扩展
  • 抽象化重构(组件框架)
    • 将通用的组件模型抽象出来

过程抽象

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

  • 高阶函数
    • 以函数作为参数
    • 以函数作为返回值
    • 常用于函数装饰器
//零阶高阶函数,等价于直接调用函数
function HOF0 (fn){
    return function(...args){
        return fn.apply(this.args);
    }
}
  • 构造 once 高阶函数,为了能够让“只执行一次”的需求(例如一些异步操作、一次性的HTTP请求)覆盖不同的事件处理,我们可以将这个需求利用闭包剥离出来。这个过程称为过程抽象。
function once ( fn ) {
    return function (...args){
    	if ( fn ) {
        	const res = fn.allpy (this.args);
        	fn = null;
        	return res;
        }
    }
}
  • 防抖函数,在第一次触发事件时,不立即执行函数,而是给出一个期限值,如果在期限值内没有再次触发滚动事件,那么就执行函数,如果在期限值内再次触发滚动事件,那么当前的计时取消,重新开始计时。
const debounce = (fn, delay = 100) => {
    let timer = null;  
    return function (...args) {
        clearTimeout(timer);
        timer = setTimeout(() => {
        	fn.apply(this,args);
        }, delay);
    }
}
  • 节流函数,类似控制阀门一样定期开放的函数,也就是让函数执行一次后,在某个时间段内暂时失效,过了这段时间后再重新激活。效果:如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效。
const throttle = (fn, delay = 500) => {
    let timer;
    return function(...args){
    	if(timer == null) {
        	fn.apply(this,args);
            timer = setTimeout(() => {
            	timer = null;
            },delay);
        }
    }
}
  • 为什么要使用高阶函数?
    • 减少系统内非纯函数的数量,提高系统的可测试性和稳定性。