javaScript | 青训营笔记

37 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天

1.javaScript

1.1 如何写好javaScript?

  • 各司其职: 让HTML,css和javaScirpt职能分离
  • 组件封装: 好的UI组件具备正确性,扩展性,复用性
  • 过程抽象:应用函数式编程思想

各司其职

我们在编写代码的时候,应当避免不必要的由js直接操作样式,可以用css的伪类来表示状态,纯展示类交互寻求零基础的js方案

组件封装

我们在编写页面的时候可以将页面上某一个功能单独抽离出来,进行封装(创建一个类,将该组件的行为方法都定义在类中, 之后我们就可以直接用该类绑定指定元素就可以实现该功能),这样不仅仅可以提高代码复用率,也易于维护

  • 在组件封装时API设计应该保持原子操作,职责单一,满足灵活性

  • 组件封装的基本流程:

    • 设计结构
    • 设计css
    • 设计行为(API功能)Event(控制流)
  • 组件优化

    • 将控制元素抽取成插件,插件与组件之间通过依赖注入建立联系
    • 将HTML模板化

过程抽象

过程抽象就像一个对象,除了有某些属性,它可以抽象成一个固定数据表示,它所拥有的动作(过程)也可以抽象一个对象, 就是我想让这个一个动作, 能让不同对象也能拥有,就可以将其单独抽离出来

例:高阶函数Once, 为了能让”只执行一次“的需求覆盖不同的事件处理,我们就可以将这个过程单独的抽离出来

      function once(fn) {
        return function (...args) {
          if (fn) {
            const ret = fn.apply(this, args)
            fn = null
            return ret
          }
        }
      }
      
      const foo = once(() => {
        console.log('bar')
      })
      // 只打印一次bar
      foo()
      foo()
      foo()

1.2 高阶函数

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

常用的高阶函数

  • Once
  • 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 / 2
  • iterative

为什么使用高阶函数

在我们编写函数时, 输入输出数据全是显式的(函数与外界交互数据的唯一渠道是参数和返回值)我们称它为纯函数, 这样的函数易于维护,非纯函数即为参数的值不用传入,他也会自动变更,这样的函数不易于维护,而使用高阶函数, 可以将非纯函数转变成为一个纯函数,在编写代码时,我们应该尽量减少非纯函数的使用

1.3 编程范式

  • 命令式
  • 声明式

命令式就像式面向过程编程, 声明式就像是面向对象

例子:

      // 命令式
      switcher.onclick = function (evt) {
        if (evt.target.className === 'on') {
          evt.target.className = 'off'
        } else {
          evt.target.className = 'on'
        }
      }


      // 声明式
      function toggle(...actions){
        return function(...args){
          let action = actions.shift()
          actions.push(action)
          return action.apply(this, args)
        }
      }

      switcher.onclick = toggle(
        evt => evt.target.className = 'off',
        evt=>evt.target.className='on'
      )

扩展

依赖注入

依赖注入(dependency injection,缩写为 DI)是一种软件设计模式,这种模式能让一个物件接收它所依赖的其他物件