如何写好JavaScript | 青训营

71 阅读2分钟

写好JS的三个原则

  • 各司其责
  • 组件封装
  • 过程抽象

各司其责

不是说要写在三个文件里,而是说负责不同的功能

举例:夜间模式的切换

使用class

将样式的编写放到CSS中,js里只切换类名

image.png

零JS方案

也可以只通过html和CSS做到(checkbox + 伪类选择器, 再将checkbox隐藏 display : none;

image.png

组件封装

组件的定义

包含HTML JS CSS 的单元

好的组件具备封装性、正确性、扩展性、复用性

举例:轮播图

实现思路

  • 通过绝对定位将图片重叠在一个位置position: absolute;
  • 定义不同的CSS选择器,通过改变类名改变样式
  • 封装一个selector类,实现切换功能

image.png

  • 自定义事件实现状态绑定(小圆点和图片对应起来)const event = new CustomEvent('slide', {bubbles:true, detail})

总结方法

  • 结构设计 html
  • 展现效果 css
  • 行为设计
    • API (功能:通过接口操作)
    • Event (控制流:自定义事件解耦)

优化

插件化 JS

解耦

  • 将控制元素抽取成插件
  • 插件和组件之间通过依赖注入方式建立联系

将轮播图下面的小圆点和左边右边的按钮分别写成插件(方法)

模板化 html

每个插件分为render 和action 方法,render负责生成html

image.png

再抽象成通用组件

包含constructor register render 方法

image.png

过程抽象

概念

不同的事件有同样的执行过程,将这个过程抽象出来

举例:只触发一次的函数(是一个高阶函数)

高阶函数 一个函数return另一个函数,常用作函数装饰器

image.png

这里形成了闭包,fn = null 之后,第二次调用会记住 fn 的值

常见应用

Throttle 节流

限制在一定时间内只能触发一次 (防连点)

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

Debounce 防抖

超过一定时间没有动作才会执行 (输入停止才会自动保存)

function debounce (fn, dur) {
    dur = dur || 100;
    var timer;
    return function () {
        clearTimeout(timer);
        timer = setTimeout (() => {
            fn.apply(this, arguments);
        }, dur);
    }
}

Consumer 延时调用

Iterative 可迭代

用一个可迭代对象依次操作多个元素

当函数不是纯函数时,至少可以保证Iterative是纯函数,方便测试

纯函数 输入相同,结果相同 没有副作用,即不改变外部元素的状态

function iterative (fn) {
    return function (subject, ...rest) {
        if (iteratable(subject)) {
            const ret = [];
            for (let obj of subject) {
                ret.push(fn.apply(this, [obj, ...rest]))
            }
            return ret;
        }
        return fn.apply(this, [subject, ...rest]);
    }
}

编程范式

命令式与声明式(js兼具两者特点)

  • 命令式写法 (强调动作,怎么做)

image.png

  • 声明式写法 (强调做什么)

image.png