JS | 青训营笔记

33 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天

写代码最应该关注什么

  • 使用场景
  • 风格
  • 效率
  • 设计
  • 约定

Leftpad事件

  • 事件本身槽点
    • NPM模块粒度
    • 代码风格
    • 代码质量/效率

屏幕截图 2023-01-16 224642.png

  • 更改后
    • 代码更简洁
    • 效率提升

屏幕截图 2023-01-16 225327.png

案例

交通灯:状态切换

  • 版本一
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);
  • 版本二:过程抽象,灵活性比较强
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();
  }
}());
  • 版本三:异步函数(比较简单)
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();

判断是否是4的幂

  • 版本一(最简单但性能较差)
function isPowerOfFour(num){
    num = parseInt(num);
    while(num > 1){
        if(num % 4) return false;
        num /= 4;
      }
      return true;
    }
  • 版本二(性能还是不够好)
function isPowerOfFour(num){
    num = parseInt(num);
    while(num > 1){
        if(num & 0b11) return false;
        num >>>= 2;
      }
      return true;
    }
  • 版本三(性能最好)

时间复杂度为O(1)

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

num.addEventListener('input', function(){
  num.className = '';
});

checkBtn.addEventListener('click', function(){
  let value = num.value;
  num.className = isPowerOfFour(value) ? 'yes' : 'no';
});
  • 另一种方法(比较有趣,性能也还可以)

正则表达式

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

洗牌

  • 版本一(不正确的)
const cards = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

function shuffle(cards) {
  return [...cards].sort(() => Math.random() > 0.5 ? -1 : 1);
}

console.log(shuffle(cards));
  • 版本二(正确)
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 < 1000000; i++) {
  const c = shuffle(cards);
  for(let j = 0; j < 10; j++) {
    result[j] += c[j];
  }
}

console.log(result);

分红包

  • 切西瓜法(代码略)

Day2总结与思考

其实对于JS,我们应该先明白我们该如何写好JS,最重要是有三个原则:

  • 各司其职

    • HTML
    • CSS
    • JS
  • 组件封装

    • 复用性
    • 可拓展性
    • 正确性
  • 过程抽象

    • 插件化
    • 模板化
    • 实现组件框架
    • 局部细节/行为的时候 函数式编程的基本应用 JS也具有声明式和命令式,但声明式有更强的可拓展性,所以在写JS时应该要考虑清楚是使用声明式还是命令式

    其实在写代码时,主要是考虑使用场景,而不是一味的追求性能,还是得多思考,而不是一股脑地写复杂的代码。

    虽然前端用的算法较少,但对于算法还是基本功,不能忽略,所以还是要学好数学,学好算法为以后着想,希望自己能开始学习算法,锻炼自己的思维能力,在之后能写出一些好的有质量的代码。