这是我参与「第四届青训营 」笔记创作活动的第26天
如何写好JavaScript代码?(一)
- 关于书籍:
- 入门书籍:犀牛书 红宝书 (厚)
- 进阶书籍:JS The Good Parts
- 书籍知识经典,但未必新,因此可以有选择性地阅读
1 遵守原则
关于什么是“好”的JS代码?应该是更灵活的、更易于维护的、考虑更加全面的。如何实现这些目标呢?首先就是要遵守以下三个原则:
- 各司其责:HTML、CSS和JavaScript分离
- 组件封装:UI界面组件实现拓展与复用
- 过程抽象:函数式编程
1.1 各司其责——结构、表现、行为分离
- 举例需求:点击按钮,实现网页夜间模式效果。
- 版本1:用js控制css,代码表示含义不清晰,且当样式需求更改时,修改麻烦。
<script>
const btn = document.getElementById('modeBtn');
btn.addEventListener('click', (e) => {
const body = document.body;
if(e.target.innerHTML === '🌞') {
body.style.backgroundColor = 'black';
body.style.color = 'white';
e.target.innerHTML = '🌜';
} else {
body.style.backgroundColor = 'white';
body.style.color = 'black';
e.target.innerHTML = '🌞';
}
});
</script>
- 版本2:在css中添加class控制样式更改,js控制行为变换,代码清晰,维护容易。
<script>
const btn = document.getElementById('modeBtn');
btn.addEventListener('click', (e) => {
const body = document.body;
if(body.className !== 'night') {
body.className = 'night';
} else {
body.className = '';
}
});
</script>
- 版本3:由于js只控制了样式变化,因此可以仅仅依赖css实现,避免js直接对样式的修改,彻底实现各司其责。
<body>
<!-- 增加一个checkbox 控制变换content样式变化 -->
<input id="modeCheckBox" type="checkbox">
<div class="content">
<header>
<!-- 为label绑定checkbox事件 -->
<label id="modeBtn" for="modeCheckBox"></label>
<h1>深夜食堂</h1>
</header>
</div>
</body>
<style>
/* 根据checkbox 选中状态 控制content的样式 实现夜间模式 */
#modeCheckBox:checked + .content {
background-color: black;
color: white;
transition: all 1s;
}
#modeCheckBox:checked + .content #modeBtn::after {
content: '🌜';
}
</style>
1.2 组件封装——正确性、拓展性、复用性
轮播图例子
- 结构-HTML
- 无序列表 ul
- 表现-CSS
- 绝对定位 position
- 修饰符 modifier
- 切换动画 transition
- 行为-JS
- API——图片轮播功能
- getSelectedItem()
- getSelectedItemIndex()
- slideTo()
- slideNext()
- slidePrevious()
- 控制流——下方小圆点事件
- 自定义事件:绑定对应顺序的小圆点与图片,实现解耦
- API——图片轮播功能
改进
- 插件化
- 将控制元素抽取成插件
- 插件与组件之间通过依赖注入建立联系
- 模板化
- 解耦:将HTML模板化,更易于扩展
- 抽象:将组件通用模型抽象出来
1.3 过程抽象——高阶函数
- 过程抽象:
- 用来处理局部细节控制的一些方法
- 将一些事件处理中共同的操作,比如“只响应一次”抽象出来,称为过程抽象
- 可以通过高阶函数实现
- 高阶函数:
- 传参和返回值都是函数
- 常用于作为函数装饰器
- 常用高阶函数:
- Once
- Throttle
- Debounce
- Consumer/2
- Iterative
- 纯函数:输入A,输出B,每次调用结果相同,可维护性高,因此建议在库中多用高阶函数
- 编程范式
- 命令式——强调怎么做
- 面向过程
- 面型对象
<script> let list = [1, 2, 3, 4]; let mapl = []; for(let i = 0; i < list.length; i++) { mapl.push(list[i] * 2); } </script>- 声明式_——做什么
- 逻辑式
- 函数式
- 具有更强的可扩展性
<script> let list = [1, 2, 3, 4]; const double = x => x * 2; list.map(double); </script> - 命令式——强调怎么做
- JS是复合型,兼容命令式和声明式风格,在代码编写时,可以考虑更多使用声明式,其更便于扩展和维护。
2 总结
- 在了解JS基础语法的基础上,如何写“好”JS代码,尽量遵守下列原则:
- 各司其责:HTML、CSS和JavaScript分离
- 组件封装:UI界面组件实现拓展与复用
- 过程抽象:函数式编程
- 勤加练习,在实践中体会上述原则