这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
JS编码原则
写好JS的一些原则
各司其职:让HTML、CSS和JavaScript职能分离
组件封装:好的UI组件具备正确性、扩展性、复用性
过程抽象:应用函数式编程思想
例子:切换深夜食堂的日间夜间模式
应当避免不必要的由JS直接操作样式;可以用class来表示状态;纯展示类建议寻求零JS方案
例子:用原生JS写一个电商网站的轮播图
结构:轮播图是一个典型的列表结构,可以用无序列表ul元素来实现
表现:使用CSS绝对定位将图片重叠在同一个位置;轮播图切换的状态使用修饰符(modifier);轮播图的切换动画使用CSS transition
行为:API
Slider
+getSelectedltem()
+getSelectedltemIndex()
+slideTo()
+slideNext()
+slidePrevious()
行为:控制流
使用自定义事件来解耦
总结:基本方法
结构设计;展现效果;行为设计:API(功能)、Event(控制流)
改进
重构:插件化
解耦 将控制元素抽取成插件;插件与组件之间通过依赖注入方式建立联系
重构:模板化
解耦
将HTML模板化,更易于扩展
组件框架
抽象
将组件通用模型抽象出来
总结:
组件设计的原则:封装性、正确性、扩展性、复用性
实现组件的步骤:结构设计、展现效果、行为设计
三次重构:插件化;模板化;抽象化(组件框架)
过程抽象
用来处理局部细节控制的一些方法;函数式变成思想的基础应用
once
为了能够让“只执行一次”的需求覆盖不同的事件处理,我们可以将这个需求剥离出来,这个过程我们成为过程抽象
HOF高阶函数
以函数作为参数;以函数作为返回值;常用于作为函数装饰器
Throttle
是一种节流技术,通常用于限制事件的触发频率。它的作用是在一段时间内只允许事件触发一次,通过限制事件的触发频率来减少不必要的处理和负载。
Debounce
是一种防抖技术,通常用于在一段时间内只响应最后一次事件。它的作用是延迟事件的触发,在事件触发后的一段时间内,如果再次触发了该事件,则取消之前的事件。
Consumer/2
是一种特殊类型的消费者函数。 它接受两个参数: 一个函数(称为“消费函数”)和一个值,并调用消费函数,将该值作为参数传递给它。
Iterative
是一种迭代的技术,通常指重复执行一段代码的过程。迭代可以用循环语句来实现,如 for 循环和 while 循环。在编程中迭代是一种常用的技巧,用于处理重复性工作,如遍历数组、字符串等。
为什么要使用高阶函数
灵活性: 高阶函数允许我们将函数作为参数或返回值,这样我们就可以在运行时动态地更改函数的行为。
可重用性: 高阶函数允许我们抽象出通用的模式,并将其封装在一个函数中,这样我们就可以重用这个函数来完成相似的任务。
组合性: 高阶函数允许我们将小函数组合成大函数,这样我们就可以使用简单的函数来构建复杂的程序。
可读性: 高阶函数允许我们将复杂的逻辑分解成多个小函数,这样我们就可以更容易地理解和维护代码。
编程范式
命令式与声明式
例子
Toggle-命令式
更直接,简洁
Toggle-声明式
可扩展性更强,在状态比较多的时候修改够更便捷
Toggle-三态
改进这段代码
检查这个矩阵是不是单位矩阵
function isUnit(){
return m[0] ===1 && m[1]===0 && m[2]===0 && m[3]===1 && m[4]===0 && m[5]===0;
}
使用数组的 every() 方法来检查所有元素是否都符合特定条件。这可以使代码更简洁和易读。
function isUnit(m) {
const expectedValues = [1, 0, 0, 1, 0, 0];
return m.every((val, idx) => val === expectedValues[idx]);
}
使用常量来存储期望值。这可以使代码更易读,并且如果需要修改期望值,只需要修改一处即可。
const UNIT_MATRIX = [1, 0, 0, 1, 0, 0];
function isUnit(m) {
for(var i=0;i<m.length;i++){
if(m[i]!== UNIT_MATRIX[i]) return false;
}
return true;
}
使用一个变量来存储单位矩阵,这样可以使比较更加简洁,例如
const UNIT_MATRIX = [1, 0, 0, 1, 0, 0];
function isUnit(m) {
return JSON.stringify(m) === JSON.stringify(UNIT_MATRIX);
}
写代码最应该关注什么
风格、效率、约定、使用场景、设计
leftpad
实现一个切换多个交通灯状态切换的功能
版本一:命令式 版本二:数据抽象 版本三:过程抽象 版本四:异步+函数式
判断是否是4的幂(力扣)
洗牌算法
random是伪随机数,在大量数据面前会出现误差 使用随机数生成器就可以避免这个情况
const crypto = require('crypto');
function shuffle(arr) {
for (let i = arr.length - 1; i > 0; i--) {
let j = crypto.randomBytes(1)[0] % (i + 1);
[arr[i], arr[j]] = [arr[j], arr[i]];
}
return arr;
}
分红包-切西瓜算法
function cutWatermelon(totalAmount, numOfPeople) {
// 红包金额最低限制
const minAmount = 0.01;
// 创建一个空数组来存储每个人分到的金额
const amounts = [];
// 记录剩余金额
let remainingAmount = totalAmount;
// 验证输入的红包金额和红包个数
if (numOfPeople < 1 || totalAmount < numOfPeople * minAmount) {
return 'Invalid input: please check the number of people or total amount.';
}
// 循环分配金额
while(true){
for (let i = 0; i < numOfPeople - 1; i++) {
// 生成一个随机数,作为当前人分到的金额
let currentAmount = (Math.random() * Math.min(remainingAmount - minAmount, (remainingAmount - minAmount * (numOfPeople-i))) + minAmount).toFixed(2);
// 将当前人分到的金额加入数组
amounts.push(currentAmount);
// 减去分到的金额
remainingAmount -= currentAmount;
}
// 剩余金额分配给最后一个人
amounts.push((remainingAmount).toFixed(2));
//如果最后一人获得的红包小于0.01,那么重新进行循环覆盖之前的数