跟着月影学JavaScript-01 | 青训营笔记

60 阅读4分钟

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

本堂课重点内容

本节课重点讲述了JavaScript的编码三大原则:各司其职、组件封装、过程抽象及各自应用。

JavaScript的编码原则之各司其职

案例:深夜食堂——通过开关控制白天/黑夜背景颜色主题切换

  • 版本1——通过DOM操作直接改变元素的style属性
  • 版本2——通过DOM操作控制元素类名的变化(常用)
  • 版本3——无JS操作版本,通过改变checkbox的checked状态属性来改变元素的样式
<input id="modeCheckBox" type="checkbox">(这个隐藏)
<div class="content">
<label id="modeBtn" for="modeCheckBox">切换按钮</label>
<!-- 这个切换就能够切换复选框状态 -->
</div>

#modeCheckBox{
    display:none;
}
#modeCheckBox:checked + .content{
    background-color:black;
    color:white;
 }

案例结论:

  • HTML/CSS/JS各司其责
  • 应当避免不必要的由JS直接操作样式
  • 可以用class来表示状态
  • 纯展示类交互寻求零JS方案

JavaScript的编码原则之组件封装

案例:轮播图组件

步骤:

  1. 使用CSS动画:使用绝对定位把图片堆叠在一起,再使用CSS动画设置图片切换效果
  2. 定义Slider类
    • getSelectItem() 获取当前元素
    • getSelectedItemIndex() 获取当前元素索引
    • slideTo() 滑到某一张
    • slideNext() 滑到下一张
    • slidePrevious() 滑到上一张

案例结论——组件封装的基本方法:

  • 结构设计
  • 展现效果
  • 行为设计(API-功能,Event-控制流 )

重构轮播图组件

1.重构之插件化

控制元素单独提取出来组成插件;插件与组件之间通过“依赖注入”方式建立联系

2.重构之模板化

将HTML模板化,更容易扩展。即定义一个类,使用render函数返回标签组合模板。

3.重构之抽象化

将组件的通用模型给抽象出来。

组件封装案例结论:

  • 设计原则:封装性、正确性、扩展性、复用性
  • 实现组件的步骤:结构设计、展现效果、行为设计
  • 三次重构:插件化、模板化、抽象化(组件框架)

改进空间:把插件和组件组合,可以有父子嵌套

JavaScript的编码原则之过程抽象

过程抽象

过程抽象是指用来处理局部细节控制的一些方法,是函数式编程思想的基础应用。

案例:实现次数控制功能

高阶函数 Once-“只执行一次”

function once(fn){
    return function(...args){
        if(fn){
            const ret = fn.apply(this,args);
            fn = null;
            return ret;
        }
    }
}

将类似于“只执行一次”这种需求从事件处理中剥离出来,这个过程就叫过程抽象

高阶函数

高阶函数(HOF):以函数为参数、函数为返回值;常用作为函数装饰器,如:

function HOF0(fn){//认为参数fn与函数HOF0是等价的
    return function(...args){return fn.apply(this,args);}
}

常用的高阶函数:

  • Once 只执行一次
  • Throttle 节流函数
  • Debounce 防抖函数(案例:小鸟跟随鼠标)
  • Consumer 延时调用
  • Iterative 迭代器,用于重复操作

为什么要使用高阶函数?

首先了解什么是纯函数?

一个函数的返回结果只依赖于它的参数 函数在执行过程里面没有任何副作用(不会造成外部变量的改变)

纯函数的优点:

  • 结果可预期的:一个固定的输入肯定会得出固定的输出
  • 没有副作用:不会对外部产生任何的影响
  • 测试方便
  • 使用纯函数可以提高库的可维护性

由于高阶函数也是纯函数,所以它具备纯函数的优点。

编程范式

声明式与命令式: 声明式代码更简洁,具有更强的可扩展性。声明式-怎么做,命令式-做什么。

案例:

  • 命令式:
switcher.onclick = function(evt){
    if(evt.target.className==='on'){evt.target.className='off'}
    else{evt.target.className='on'}
}
  • 声明式:
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'
}

个人总结

通过案例代码的层层递进、一步步剖析,逐渐理解了代码优化的妙处。在以后的编码中,我也要逐渐养成优秀的编码思想,勤加练习。

参考文章

简单解读高阶函数和纯函数 https://juejin.cn/post/6844903769444974606