这是我参与 第五届青训营 伴学笔记创作活动的第7天
写代码最应该关注什么?
- 为自己,清晰、职责分明、可维护的代码有利于后期迭代
- 为他人,离职了以后同事能更好地交接
- 观察并吸收同事优秀的代码风格
- 代码可读性放在第一位
- 注意大的性能优化
- 学习并使用设计模式(理解业务的基础上)
交通灯
交通灯切换状态代码
是实现一个切换多个交通灯状态切换的功能。
版本一
setTimeOut多层嵌套
使用setTimeOut函数来实现这一功能。但由于它是异步的,需要嵌套五层。虽然代码是可以运行的,但它的可维护性和美观程度都比较差。
const traffic = document.getElementById('traffic');
(function reset(){
traffic.className = 's1';
setTimeout(function(){
traffic.className = 's2';
setTimeout(function(){
traffic.className = 's3';
setTimeout(function(){
traffic.className = 's4';
setTimeout(function(){
traffic.className = 's5';
setTimeout(reset, 1000)
}, 1000)
}, 1000)
}, 1000)
}, 1000);
})();
版本二
数据抽象
定义一个start方法,使用递归的方式更加优雅地实现了这一功能,交通灯的不同状态抽象成了列表stateList方便状态的增删与修改。
const traffic = document.getElementById('traffic');
const stateList = [
{state: 'wait', last: 1000},
{state: 'stop', last: 3000},
{state: 'pass', last: 3000},
];
function start(traffic, stateList){
function applyState(stateIdx) {
const {state, last} = stateList[stateIdx];
traffic.className = state;
setTimeout(() => {
applyState((stateIdx + 1) % stateList.length);
}, last)
}
applyState(0);
}
start(traffic, stateList);
版本三
过程抽象
将轮巡poll与等待wait的过程定义成了单独的方法,使用到了过程抽象的概念。虽然过程抽象后得到的代码明显变多,但得到了通用的过程方法,可以更方便地扩展到其他领域,更加灵活。
const traffic = document.getElementById('traffic');
function wait(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function poll(...fnList){
let stateIndex = 0;
return async function(...args){
let fn = fnList[stateIndex++ % fnList.length];
return await fn.apply(this, args);
}
}
async function setState(state, ms){
traffic.className = state;
await wait(ms);
}
let trafficStatePoll = poll(setState.bind(null, 'wait', 1000),
setState.bind(null, 'stop', 3000),
setState.bind(null, 'pass', 3000));
(async function() {
// noprotect
while(1) {
await trafficStatePoll();
}
}());
版本四
异步、函数式
版本三中的代码相对来说不容易理解。而这一版本地代码就提高了代码的可读性,更贴近自然的理解模式。对于轮巡操作,主要包括状态的设置和等待若干时间后再设置下一个状态,前者可以通过setState实现,后者可以通过wait方法实现。
const traffic = document.getElementById('traffic');
function wait(time){
return new Promise(resolve => setTimeout(resolve, time));
}
function setState(state){
traffic.className = state;
}
async function start(){
//noprotect
while(1){
setState('wait');
await wait(1000);
setState('stop');
await wait(3000);
setState('pass');
await wait(3000);
}
}
start();
2023/1/24 Day7