组件是指Web页面上抽出来的一个个包含模块(HTML)、样式(CSS)和功能(JS)的单元。好的组件具备封装性、正确性、扩展性、复用性。实现组件的步骤:结构设计、展现效果、行为设计,三次重构:插件化重构、模板化重构、抽象化重构。
过程抽象是指用来处理局部细节控制的一些方法,是函数式编程思想的基础应用。
//零阶高阶函数,等价于直接调用函数
function HOF_0 (fn){
return function(...args){
return fn.apply(this.args);
}
}
function once ( fn ) {
return function (...args){
const res = fn.allpy (this.args);
fn = null;
return res;
}
}
防抖函数,在第一次触发事件时,不立即执行函数,而是给出一个期限值,如果在期限值内没有再次触发滚动事件,那么就执行函数,如果在期限值内再次触发滚动事件,那么当前的计时取消,重新开始计时
节流函数,类似控制阀门一样定期开放的函数,也就是让函数执行一次后,在某个时间段内暂时失效,过了这段时间后再重新激活。效果:如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效。
为什么要使用高阶函数?
常规操作
优化版本1,利用 4 的幂的二进制数最高位为1,低位为偶数个0
优化版本2,利用正则表达式
const isPowerOfFour = (num) => {
num = parseInt(num).toString(2);
return /^1(?:00)*$/.test(num);
}
版本一,利用setTimeout,可能出现回调地狱
优化版本,利用async/await
错误示例 看似可以正确洗牌,但实际上较小的牌放到前面的概率更大,较大的的牌放到后面的概率更大
正确示例
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];
}
return c;
}
版本一,类似于切蛋糕,取最大的继续切分,得出的结果会比较平均
版本二,随机性较大,可能会有较大的红包出现
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]
}
return c;
}
function generate(amount,count){
if(count <= 1) return [amount];
const cards = Array(amount - 1).fill(null).map((_,i) => i+1);
const pick = draw(cards);
const result = [];
for(let i = 0 ; i < count; i++){
result.push(pick.next().value);
}
result.sort((a,b)=>a-b);
for(let i = count - 1 ; i > 0 ; i--){
result[i] = result[i] - result[i - 1];
}
return result;
}