如何写好JavaScript2 | 青训营笔记

58 阅读1分钟

image.png

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

过程抽象

  • 用来处理局部细节控制的一些方法
  • 函数式编程思想的基础应用
function once(fn) {
  return function(...args) {
    if(fn) {
      const ret = fn.apply(this, args);
      fn = null;
      return ret;
    }
  }
}

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

const list = document.querySelector('ul');
const buttons = list.querySelectorAll('button');
buttons.forEach((button) => {
  button.addEventListener('click', once((evt) => {
    const target = evt.target;
    target.parentNode.className = 'completed';
    setTimeout(() => {
      list.removeChild(target.parentNode);
    }, 2000);
  }));
});

const foo = once(() => {
  console.log('bar');
});

foo();
foo();
foo();

——>

操作次数限制

  • 一些异步交互
  • 一次性的HTTP请求

高阶函数

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

常用高阶函数

  • Once
function once(fn) {
  return function(...args) {
    if(fn) {
      const ret = fn.apply(this, args);
      fn = null;
      return ret;
    }
  }
}
  • 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);
  }
}
  • 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]);
  }
}

高级函数——>纯函数——>多使用纯函数

纯函数

//纯函数
function add(x,y){
  return x+y;
}
//非纯函数
let idx=0;
function count(){
  idx++;
}

编程范式

命令式与声明式

//命令式实例
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'
);
//声明式更强的可扩展性 新增方法

//三态
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 = 'warn',
  evt => evt.target.className = 'off',
  evt => evt.target.className = 'on'
);

总结

  • 过程抽象 / HOF / 装饰器
  • 命令式 / 声明式