JavaScript| 青训营笔记

45 阅读3分钟

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

写好JS的一些原则

  • 各司其责:让HTML、CSS和JavaScript职能分离。
    • 应当避免不必要的由JS直接操作样式
    • 可以用class来表示状态
    • 纯展示类交互寻求零JS方案
    • eg:夜间白天切换,尽量分开CSS和Javascript的部分,样式的变化在CSS中,Javascript只改变class的状态,或者直接用CSS的伪类选择器改变样式
  • 组件封装:好的UI组件具备正确性、扩展性、复用性。
    • 结构设计html
    • 展现效果css
    • 行为设计JavaScript : API (功能)、Event (控制流)
    eg:轮播图,在HTML中定义列表等,在CSS中利用绝对定位和相对定位确定位置,在Javascript中设计实现轮播的具体功能
    ⭐重构:插件化
    • 将控制元素抽取成插件
    • 插件与组件之间通过依赖注入方式建立联系
    ⭐重构:模板化
    • 将HTML模板化,易于扩展(在Javascript中根据数据生成对应的html文本)
    ⭐重构:组件框架(有点抽象,需要后期实践)
    • 将通用组件模型抽象出来
  • 过程抽象:应用函数式编程思想。
    • 高阶函数实现(以函数为参数,以函数为返回值,常用作函数装饰器),eg:让函数只执行一次抽象得到的once()函数
    • //高阶函数基本架构
      function HOFO(fn) {
          return function(..args) {
              return fn,apply(this, args);
          }
      }
      
      //once高阶函数实现
      function once(fn) {//输入的是一个函数
          return function (...args) {
              if(fn) {//只有第一次执行的时候fn!=null,之后都是null
                  const ret = fn.apply(this, args);
                  fn=null;//用这个
                  return ret ;
              }
          };
      }
      
      function throttle(fn, time = 500){
        let timer;//只执行一次
        return function(...args){
          if(timer == null){
            fn.apply(this,  args);
            timer = setTimeout(() => {
                timer = null;//执行完这句才能再次执行这个函数
            }, time)
          }
        }
      }
      

      高阶函数的使用可以减少非纯函数(输出不确定)的出现。

      //将列表中的奇数位置元素设置为红色
      const isIterable = obj => obj != null 
        && typeof obj[Symbol.iterator] === 'function';
      
      function iterative(fn) {
        return function(subject, ...rest) {
          if(isIterable(subject)) {//这里会判断subject是否是一个列表,如果是,那么列表中的每一个元素+...rest执行该函数
            const ret = [];
            for(let obj of subject) {
              ret.push(fn.apply(this, [obj, ...rest]));
            }
            return ret;
          }
          return fn.apply(this, [subject, ...rest]);
        }
      }
      
      const setColor = iterative((el, color) => {
        el.style.color = color;
      });
      
      const els = document.querySelectorAll('li:nth-child(2n+1)');
      setColor(els, 'red');
      
    • 命令式与声明式
    • //状态转换(声明式)
      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 = 'off',
        evt => evt.target.className = 'on'
      );
      

      如果增加状态是很容易的,只要在第二个函数添加状态即可。如果采用if-else增加状态就比较麻烦了。这就是命令式(怎么做)与声明式(做什么)的区别。

如何更好地优化代码

  • 交通灯:嵌套🙁、抽象😊(不要过度抽象)
  • 4的幂:
function isPowerOfFour(num){
    num = par seInt(num) ;
    return num > 0 &&
    (num&(num-1))===0&&//判断是否为2的幂(eg:8&7=0,7&6!=0)
    (num & 0xAAAAAAAA) === 0;//判断是否为4的幂(4=100,4的幂1必然在奇数位,0xAAAAAAAA=1010...1010)
}
function isPowerOfFour(num){
    num = parseInt(num).toString(2);
    return /^1(?:00)*$/.test(num);//4的幂1必然在奇数位
}
  • 分红包:切西瓜法、抽牌法