【青训营】- 第2天学JavaScript

项目/代码优化迭代重构

  1. 实现,正确性
  2. 简洁简明易懂,可读性,注释,结构清晰,去掉冗余代码
  3. 风格统一,代码规范,设计模式,可扩展性,封装,模块化
  4. 架构优化,性能优化

case1:Left-pad事件是什么事件?

待整理补充

case2:交通灯状态切换

初版代码

不及格.js

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);
})();

复制代码

版本1.1

数据封装-数据抽象
version1.js

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

复制代码

版本1.2

version2.js

const traffic = document.getElementById('traffic');

function polll(...fnList) {
    let stateIndex = 0;
    return function(...args){
        let fn = fnList[stateIndex++ % fnList.length];
        return fn.apply(this, args);
    }
}

function setState(state){
    traffic.className = state;
}

let trafficStatePoll = poil(SetState.bind(null, 'wait),
                            SetState.bind(null, 'stop),
                            SetState.bind(null, 'pass));
setInterval(trafficStatePoll, 2000);

复制代码

版本1.3

const traffic = document.getElementById('traffic');

function wait(time){
    return new Promise(resolve => setTimeout(resolve, time));
}

function setState(state){
    traffic.className = status;
}

async function start(){
    //noprotect
    while(1){
        setState('wait');
        await wait(1000);
        setState('stop');
        await wait(3000);
        setState('pass');
        await wait(3000);
    }
}

start();

复制代码

发布版和小结

还有更复杂的方法。

这次课程是强代码教学,在实际开发项目中体会和学习掌握程序优化。
但就我本身学习习惯,一个程序经过4次迭代重构,每一次的演进很精彩,但时间被拉长,过长的时间分散掉注意力,如果控制在3次及以内,或者预告迭代版本数量,可能更能提升体验。好处就是有时间回顾一下没有掌握的知识点,有机会相对自由地分配精力。

case3:判断是否是4的幂

版本1

function isPowerOfFour(num){
    num = parseInt(num);
    
    while(num > 1){
        if(num % 4) return false;
        num /=4;
    }
    return true;
}
    
复制代码

版本1.1

function isPowerOfFour(num){
    num = parseInt(num);
    
    return num > 0 && (num & (num - 1)) === 0 && (num & 0xAAAAAAAA) === 0;
}    

复制代码

版本1.2 正则表达式

function isPowerOfFour(num){
    num = parseInt(num).toString(2);
    
    return /^(?:00)*$/.test(num);
}    

复制代码

发布版和小结

还有没有想到更好的方法?
我很喜欢这样开放式的鼓励。

但感觉两个案例就需要静下来消化一下了,但讲师已经马上进入下一个案例的分析了。
课程上到这里,就有一点吃力了,我的上课状态进入第二阶段,情绪稍有低落。
接下来就是对我专注力的挑战了。

case4:洗牌算法:正确性

版本1

const cards = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
function shuffle(cards) {
    return [...cards].sort(() => Math.random() > 0.5 ? -1: 1);
}

const result = Array(10).fill(0);

for(let i = 0; i < 10000; i++) {
    const c = shuffle(cards);
    for(let j = 0; j < 10; j++) {
        result[j] += c[j];
    }
}

console.log(result);
复制代码

版本1.2 OK版

数学归纳法

const cards = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
function shuffle(cards) {
    const c = [...cards];
    for(let i = c; i > 0; i--) {
        const pIdx = Math.floor(Math.random()*i);
        [c[pIdx], c[i-1] = [c[i-1], c[pIdx]];
    }
    return c;
}

const result = Array(10),fill(0);

for(let i=0; i<10000; i++) {
    const c= shuffle(cards);
    for(let j=0; j<10; j++) {
        result[j] += c[j];
    }
}

console.log(shuffle(cards));
console.log(result)
复制代码

版本1.3 生成器版

1000张

const cards = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
function draw(cards) {
    const c = [...cards];
    for(let i = c.length; i > 0; i--) {
        const pIdx = Math.floor(Math.random()*i);
        [c[pIdx], c[i-1] = [c[i-1], c[pIdx]];
        yield c[i-1];
    }
}

const result = draw(cards);
console.log([...result])
复制代码

项目小结

力不从心。
我习惯实现代码,是练习也是检验自己的掌握情况。
虽然讲师用心准备好代码,系统细化知识点,但以我的速度还是没有办法即时运行调试通过demo代码,
成就感较低,动力受挫。希望有简化案例,5分钟随堂案例实现,以提升积极性和参与感。

红包生成器

版本1 PPT版(红包金额均匀)

.js 挑选出最大的一块进行切分

function generate(amout, count){
    let ret = [amount];
    

    while(count > 1){
        let cake = Math.max(...ret),
            idx = ret.indexOf(cake),
            part = 1 + Math.floor((cake / 2)* Math.random(1)),
            rest = cake - part;
        ret.splice(idx, 1, part, rest);
        
        count--;
    }
    return ret;
}

const amountEl = document.getElementById('amount');
const countEl = document.getElemnetById('count')
const generateBtn = document.getElemnetById('generateBtn')
const resultEl = document.getElemnetById('result')

复制代码

error:点击随机生成按钮未显示结果
image.png
.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <h2>红包生成器</h2>
  <div id="setting">
      <div><label>红包金额:<input id="amount" value=100.00></input></label></div>
      <div><label>红包金额:<input id="amount" value=100.00></input></label></div>
      <div><button id="generateBtn">随机生成</button></div>
  </div>
  <url id="result"></ul>
</body>
</html>
复制代码

版本1.2 随机生成n个切割位置(金额随机)

const cards = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
function draw(cards) {
    const c = [...cards];
    for(let i = c.length; i > 0; i--) {
        const pIdx = Math.floor(Math.random()*i);
        [c[pIdx], c[i-1] = [c[i-1], c[pIdx]];
        yield c[i-1];
    }
}

function generate(amout, count){
    if(count <= 1) return [amount];
    const cards = Array(amount - 1).fill(0).map((_, i) => i + 1);
    const pick = draw(cards);
    const result = [];
    for(let i = 0; i< count; i++) {
        result.push(pick.next().value);
    }
    result.sort((a, b) => a- b);
    for(let i = count - 1; i > 0; i--) {
        result[i] = result[i] - result[i-1];
    }
    return result;
}

复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享