这是我参与「第五届青训营」伴学笔记创作活动的第 3 天,作为一个前端基础一般的人,这几天的知识着实需要慢慢消化啊T^T
一、本堂课重点内容:
- JavaScript的职能
- 如何优化JavaScript代码
- 通过三个代码实践分析优化思路
二、详细知识点介绍:
引入
-
HTML、CSS、JavaScript 应 各司其职,职能分离
-
例子:主题切换
样式的变换避免直接写在JavaScript中,JS只负责行为,具体样式设置放在CSS中是最好的。
为什么:
-
便于其他开发者理解
-
便于维护
此外,纯展示类互动应追求零JS方案
组件封装
组件是指web页面上抽出来一个包含模板(HTML),功能(JavaScript),样式(CSS)的单元。
组件应该具备:
- 封装性
- 正确性
- 扩展性
- 复用性
以轮播图为例
-
结构:HTML 列表
-
表现:CSS 设置其样式,如过渡动画,重设排版
-
行为:JavaScript API +自定义事件实现轮播,手动切换等
总结:基本方法:
-
结构设计
-
展现效果
-
行为设计(包括功能和控制流)
重构组件
插件化
我感觉这一步就是函数封装的思想,将不同的功能细分后封装成不同的插件,然后注入组件,就能实现功能解耦,方便代码的维护调整
更进一步:HTML模板化
将各个功能及其构件进一步封装成模板,大大提高扩展性
再进一步:组件抽象化
抽象出通用模型,变成组件框架,进一步提高扩展性
老师提醒:各司其职不代表要各自写在不同文件中,而是说其本质负责的功能不混淆,各自负责自己的任务。
总结:
优化思路:二次重构
- 插件化
- 模板化
- 抽象化(组件框架)
提高代码的复用性与扩展性
过程抽象
以高阶函数 (以函数为参数及返回值) once为例
为了能够让只执行一次的需求覆盖不同的事件处理,将这个需求剥离出来。这个过程称为过程抽象。
- 我个人感觉还是函数封装的思想
高阶函数的作用
这里讲了很久纯函数和非纯函数,有点晕
例子:
利用高阶函数iterative将非纯函数转化为纯函数简化测试,(这点我没有听懂,我cpu过载了) 这一点真的抽象
总结
高阶函数可以减少非纯函数,尽量使用纯函数以保证过程的可预测性,提高代码的可维护性,减少错误。
编程范式:
-
命令式:强调怎么做
-
声明式:强调做什么
JavaScript同时具备两种特点
- 命令式写法更简洁
- 声明式写法更容易封装扩展。
不能单凭代码风格去评判代码好坏,要根据实际应用场景灵活运用,有时“笨办法”也很好用
- 例子:2016年LeftPad事故
三、实践练习例子:
时间有限,所以只做了部分代码实践。
主题切换
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>主题切换</title>
<link href="CSS/1.css" type="text/css" rel="stylesheet">
</head>
<body>
<header>
<button id="modeBtn"></button>
<h1>JavaScript初尝试</h1>
</header>
<main>
<div class="pict">
<img src="kara-art.jpg" alt="" >
</div>
<div class="description">
<p>
本节课从实践维度解读在实际编码过程中何种类型的 JavaScript 代码
称之为“好代码”,并从 JS 出发,总结其他语言编码可遵循的共性原则,
由浅入深,该小节将集中讲解三大原则之一的“各司其职”原则。
</p>
</div>
</main>
<script src="JS/1.js"></script>
</body>
</html>
body,html {
width: 100%;
height: 100%;
max-width: 600px;
padding: 0;
margin: 0;
overflow: hidden;
}
body {
padding: 10px;
box-sizing: border-box;
transition: all 1s;
}
div.pict img {
width: 100%;
}
#modeBtn {
font-size: 2rem;
float: right;
border: none;
outline: none;
cursor: pointer;
background: inherit;
}
body.night {
background-color: black;
color: white;
transition: all 1s;
}
#modeBtn::after {
content: '☀';
}
body.night #modeBtn::after{
content: '🌙';
}
const btn = document.getElementById('modeBtn');
btn.addEventListener('click',(e)=>{
const body=document.body;
if(body.className !== 'night'){
body.className = 'night';
} else {
body.className = '';
}
});
实现效果:
分红包(切西瓜法)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>红包</title>
<link href="CSS/2.css" type="text/css" rel="stylesheet">
</head>
<body>
<header>
<h1>红包模拟器</h1>
</header>
<main>
<div id="setting">
<div><label>红包金额:<input id="amount" value=100.00></label></div>
<div><label>红包数量:<input id="count" value="10"></label></div>
<div><button id="generateBtn">分红包</button></div>
</div>
<ul id="result">
</ul>
</main>
<script src="JS/2.js"></script>
</body>
</html>
#setting button {
margin-top: 20px;
color: red;
}
#setting label{
color: red;
}
#result {
padding: 0;
border: 2px solid #ec0505;
}
#result li {
border: 2px solid #ec0505;
}
function generate(amount, count){
let ret = [amount];
while(count > 1){
//挑选出最大一块进行切分
let cake = Math.max(...ret),
idx = ret.indexOf(cake),
part = 1 + Math.floor((cake / 2) * Math.random()),
rest = cake - part;
ret.splice(idx, 1, part, rest);
count--;
}
return ret;
}
const amountEl = document.getElementById('amount');
const countEl = document.getElementById('count');
const generateBtn = document.getElementById('generateBtn');
const resultEl = document.getElementById('result');
generateBtn.onclick = function(){
let amount = Math.round(parseFloat(amountEl.value) * 100);
let count = parseInt(countEl.value);
let output = [];
if(isNaN(amount) || isNaN(count)
|| amount <= 0 || count <= 0){
output.push('输入格式不正确!');
}else if(amount < count){
output.push('钱不够分')
}else{
output.push(...generate(amount, count));
output = output.map(m => (m / 100).toFixed(2));
}
resultEl.innerHTML = '<li>' +
output.join('</li><li>') +
'</li>';
}
代码参考月影老师的课程源码
切西瓜法可以避免直接用随机数时出现的先分了一部分红包,剩下的不够分的情况,它每次分都是基于“最大块”的“自我分离”,避免了出现溢出的情况。
效果:
四、课后个人总结:
难点:
- 本节课个人认为最难懂是过程抽象中的高阶函数作用,那个iterative函数的部分很容易绕晕
总结:又是知识点满满的一天,讲了很多内容,但老师的讲解让我进一步地理解了代码优化的重要性。如何写好前端代码,首先要记住设计步骤:
-
结构设计
-
展现效果
-
行为设计(包括功能和控制流)
其次是代码优化:
- 插件化
- 模块化
- 抽象化
总而言之,要提高代码的可读性、复用性、扩展性。最重要一点是要根据应用场景灵活使用代码,不要墨守成规,哪种代码更适合就用哪种,不必过于追求无意义的优化。
文章如有错漏,请多多包涵