【青训营】03 - 如何写好JavaScript - 编程范式

157 阅读1分钟

好的代码是由工程师决定的,而非编程语言决定的。

命令式与声明式

let list = [1, 2, 3, 4];

// 命令式
let res = [];
for(let i = 0; i < list.length; ++i) {
  res.push(list[i] * 2);
}

// 声明式
const double = x => x * 2;
list.map(double);

JavaScript本身同时支持命令式与声明式的编程,但二者所强调的内容是不同的。

  • 命令式风格:强调怎么做,上例中明确对每个元素计算;
  • 声明式风格:强调是什么,上例中创建了double算子;

例子 切换按钮

ha2nh-gfue5.gif

HTML

<div id="switcher" class="on"></div>

CSS

#switcher {
  display: inline-block;
  background-color: black;
  width: 50px;
  height: 50px;
  line-height: 50px;
  border-radius: 50%;
  text-align: center;
  cursor: pointer;
}

#switcher.on {
  background-color: green;
}

#switcher.warn {
  background-color: yellow;
}

#switcher.off {
  background-color: red;
}

#switcher.on:after {
  content: 'on';
  color: white;
}

#switcher.warn:after {
  content: 'warn';
  color: black;
}

#switcher.off:after {
  content: 'off';
  color: white;
}

命令式

JavaScript

switcher.onclick = function(evt){
  if(evt.target.className === 'on'){
    evt.target.className = 'off';
  }else{
    evt.target.className = 'on';
  }
}

声明式

JavaScript

function toggle(...actions){ // 定义了一个过程toggle来进行状态切换
  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'
);

直观的看上去,声明式的代码比命令式的代码要复杂的多。声明式做了一层抽象,使用toggle()(队列)来维护状态的出现顺序。这样做的好处是什么呢?如果我们添加一个状态warn

b1png-6sweq.gif

那么仅需添加warn状态即可,对代码本身的逻辑没有侵入性。

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'
);

所有的抽象都是为了提升可扩展性。

参考资料