好的代码是由工程师决定的,而非编程语言决定的。
命令式与声明式
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算子;
例子 切换按钮
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:
那么仅需添加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'
);
所有的抽象都是为了提升可扩展性。