这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
一、本堂课重点内容:
- 如何写好JavaScript
- 各司其责
- 组件封装
- 过程抽象
- 写代码应该关注的要点
二、详细知识点介绍:
2.1 各司其责
- HTML/CSS/JS各司其责
- 应当避免不必要的由JS 直接操作样式
- 可以用class 来表示状态
- 纯展示类交互寻求零JS方案
例子:
-
HTML/CSS/JS各司其责
-
可以用class 来表示状态
-
这个例子体现了纯展示类交互寻求零JS方案
2.2 组件封装
组件是指Web页面上抽出来一个个包含模版((HTML)、功能(JS)和样式(CSS)的单元。好的组件具备封装性、正确性、扩展性、复用性。
总结:
- 组件设计的原则:封装性、正确性、扩展性、复用性
- 实现组件的步骤:结构设计、展现效果、行为设计
- 三次重构
- 插件化
- 模板化
- 抽象化(组件框架)
实现的代码
2.3 过程抽象
- 用来处理局部细节控制的一些方法
- 函数式编程思想的基础应用
once
- 为了能够让“只执行一次“的需求覆盖不同的事件处理,我们可以将这个需求剥离出来。这个过程我们称为
过程抽象。
// 实现once
function once(fn) {
return function () {
if (fn) {
const ret = fn.apply(this, arguments);
fn = null;
return ret;
}
};
}
button.addEventListener('click', once((evt) => {
const target = evt.target;
target.parentNode.className = 'completed';
setTimeout(() => {
list.removeChild(target.parentNode);
}, 2000);
}));
2.4 高阶函数
- 以函数作为参数
- 以函数作为返回值
- 常用于作为函数装饰器
2.5 编程范式
命令式与声明式
- 命令式
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'
);
- 三态
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 = 'warn',
evt => evt.target.className = 'off',
evt => evt.target.className = 'on'
);
总结
- 过程抽象/HOF/装饰器
- 命令式/声明式
三、实践练习例子:
-
实现交通灯
-
判断是否是4的幂
- 洗牌
const cards = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
function shuffle(cards) {
const c = [...cards];
for(let i = c.length; i > 0; i--) {
const pIdx = Math.floor(Math.random() * i);
[c[pIdx], c[i - 1]] = [c[i - 1], c[pIdx]];
}
return c;
}
const result = Array(10).fill(0);
for(let i = 0; i < 10000; i++) {
const c = shuffle(cards);
for(let j = 0; j < 10; j++) {
result[j] += c[j];
}
}
console.log(shuffle(cards));
console.log(result);
const cards = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
function * draw(cards){
const c = [...cards];
for(let i = c.length; i > 0; i--) {
const pIdx = Math.floor(Math.random() * i);
[c[pIdx], c[i - 1]] = [c[i - 1], c[pIdx]];
yield c[i - 1];
}
}
const result = draw(cards);
console.log([...result]);
- 红包生成器
四、课后个人总结:
各司其责指的是HTML/CSS/JS各自负责自己的工作,避免不必要的由JS直接操作样式,可以用class来表示状态,寻求零JS方案来实现纯展示类交互。
组件封装是指将Web页面上的模板(HTML)、功能(JS)和样式(CSS)抽出来作为一个单元来处理。好的组件具备封装性、正确性、扩展性和复用性。
过程抽象是指用来处理局部细节控制的一些方法。这是函数式编程思想的基础应用,可以实现“只执行一次”等需求。