学习JavaScript | 青训营笔记

78 阅读2分钟

这是我参与「第四届青训营 」笔记创作活动的的第2天

写好JS的一些原则

各司其职、组件封装、过程抽象

各司其职

  • 让HTML,CSS,JavaScript职能分离
  • 应当避免不必要的由JS直接操作样式
  • 可以用class来表示状态
  • 纯展示类交互寻求零JS方案

组件封装

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

设计一个UI组件的基本方法

  • 结构设计
  • 展现效果(CSS)
  • 行为设计:API(功能,设计一些接口来操作),Event(控制流,用自定义事件来解耦)

重构:插件化
将控制元素抽取成插件
插件与组件之间通过依赖注入方式建立联系
将插件和组件融合在一起,子组件作为父组件的插件来使用

重构:模板化
将HTML和CSS模板化,更易于扩展

组件框架
将组件通用模型抽象出来

过程抽象

用来处理局部细节控制的一些方法
应用函数式编程思想,用高阶函数来实现过程抽象

高阶函数---HOF(函数装饰器)

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

等价高阶函数

function HOF0(fn) {
    return function(...args) {
      return fn.apply(this, args);
    }
  }

常用的高阶函数

Once

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

function once(fn) {
  return function(...args) {
    if(fn) {
      const ret = fn.apply(this, args);
      fn = null;
      return ret;
    }
  }
}
Throttle---截流函数

每隔500毫秒记录一次

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

每隔一个时间调用一次function,将同步调用的function变成异步调用

function consumer(fn, time){
  let tasks = [],
      timer;
  
  return function(...args){
    tasks.push(fn.bind(this, ...args));
    if(timer == null){
      timer = setInterval(() => {
        tasks.shift().call(this)
        if(tasks.length <= 0){
          clearInterval(timer);
          timer = null;
        }
      }, time)
    }
  }
}
Iterative

可迭代方法,同时操作多个元素

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

为什么要使用高阶函数?

纯函数:结果是可预期的,容易测试正确性
在一个库里,我们尽量使用纯函数,减少非纯函数的使用,可以提升库的可维护性
使用高阶函数,可以大大减少非纯函数的使用