这是我参与「第四届青训营」笔记创作活动的第 2 天
一、本堂课重点内容:
- JavaScript 三个原则
- 编程范式
- 部分算法
二、详细知识点介绍:
JavaScript 三个原则
各司其责 - 让三大件职能分离
- 应当避免不必要的由 JS 直接操作样式
- 纯展示类交互寻求零 JS 方案
组件封装 - 封装性、正确性、扩展性、复用性
基本方法
- 结构设计 - HTML
- 展现效果 - CSS
-
行为设计 - JavaScript
- API (功能)
- Event (控制流)
重构方向
-
插件化 - 让组件更加的灵活
-
将控制元素抽取成插件
-
插件与组件之间通过依赖注入方式建立联系
-
可以添加以下函数到类内进行注册插件操作
-
registerPlugins(...plugins){ plugins.forEach(plugin => plugin(this)); }
-
-
-
模板化 - 将 HTML 模板化更易于扩展
- 可以在类内创建一个 render() 函数
- 抽象化 - 通过编写一个抽象类当作接口进行操作
过程抽象 - 应用函数式编程思想
- 用来处理局部细节控制的一些方法
高阶函数(HOF)
- 让功能需求覆盖到不同的事件处理,将事件抽象成高阶函数则为一种过程抽象
- 高阶函数一般为纯函数
结构
function HOF0(fn) {
return function(...args) {
return fn.apply(this, args);
}
}
- 以函数作为参数
- 以函数作为返回值
- 常用于作为函数装饰器
常用高阶函数
- Once - 操作次数限制
- Throttle - 节流(限制操作频率)
- Debounce - 防抖函数
- Consumer - 计算函数
- Iterative - 批量操作函数
例子 - 操作次数限制
function once(fn) {
return function(...args) {
if(fn) {
const ret = fn.apply(this, args);
fn = null;
return ret;
}
}
}
const foo = once(() => {
console.log('bar');
});
foo();
foo();
foo();
虽然使用了三次 foo 函数,但是实际上仅会输出一次 "bar" 。原因在于 foo 的返回值是一个函数而该函数在调用一次过后则变为 NULL ,导致第二次在判断时为 False 无法进入从而实现限制操作次数的功能
纯函数
特点
- 如果函数的调用参数相同,则永远返回相同的结果。它不依赖于程序执行期间函数外部任何状态或数据的变化,必须只依赖于其输入参数。
- 该函数不会产生任何可观察的副作用
- 纯函数相较于非纯函数有较高的可维护性
编程范式
JavaScript 支持命令式和声明式两种
命令式范式 - 告诉程序如何做
- 面向过程
- 面向对象
声明式范式 - 告诉程序做什么
声明式范式的代码会较为简洁
-
函数式编程
- 拥有更高的可扩展性
- 逻辑式编程
判断是否为 4 的幂
位与运算符 &
- 用于对两个二进制操作数逐位进行比较
| 第一个数位值 | 第二个数位值 | 运算结果 |
|---|---|---|
| 1 | 1 | 1 |
| 1 | 0 | 0 |
| 0 | 1 | 0 |
| 0 | 0 | 0 |
- 当数为 2 的幂时,该数的二进制仅有一个 1
- 当数为奇数时,该数的二进制的个位为 1 ,反之亦然
方法一
function isPowerOfFour(num){
num = parseInt(num);
return num > 0 &&
(num & (num - 1)) === 0 &&
(num & 0xAAAAAAAAAAAAA) === 0;
}
解析
num > 0
- 4 的幂均大于 0
num & (num - 1) === 0
num 和 (num - 1) 必然其中一个为奇数,一个为偶数。
因此两者进行运算时,必然会消去 num 的一个 1
又因为当该数为 2 的幂时,该数的二进制仅有一个 1,因此运算结果即为 0
(num & 0xAAAAAAAAAAAAA) === 0
- 0xAAAAAAAAAAAAA 转二进制为 1010101010101010101010101010101010101010101010101010
因为 4 的幂的数的二进制(从右往左数)偶数位不能为 1
若偶数位包含 1 则运算结果不为 0 故能判断该值是否为 4 的幂
其中,A 的个数取决于 JavaScript 的精度为 64 位的浮点数,其中有 11 位的小数位,因此整数的精度为 53 位
方法二
function isPowerOfFour(num) {
num = parseInt(num).toString(2);
return /^1(?:00)*$/.test(num);
}
解析
#2 - 将 num 转换为一个二进制字符串
#3 - 进行正则表达式匹配,若 1 后有偶数个 0 则为真,反之为假
分红包
切西瓜法
- 每次切都切最大的一块
- 时间复杂度 O(M*N)
- 缺点在于小的那一块不会进行切割
抽牌法
- 时间复杂度 O(N)
- 缺点在于空间复杂度较高(需要创建随机数列)
- 生成一个随机数列
- 用生成器从数列中取若干个
- 将指传递到数组并将数组排序
- 通过前减后来获取红包值