这是我参与「第五届青训营 」笔记创作活动的第6天
一、本堂课重点内容:
- 过程抽象概念
- 高阶函数使用模式
- JavaScript 编程范式
二、详细知识点介绍:
过程抽象概念
过程抽象是一种设计模式,它允许将一组相关的操作封装在一起,而不关注这些操作的具体实现细节。这样,我们就可以在使用这些操作的地方,只关注它们的行为而不关心它们的实现。
在 JavaScript 中,过程抽象可以通过函数来实现。函数就是一组封装在一起的操作,可以在需要时调用。通过将实现细节隐藏在函数内部,我们可以避免在调用函数时过多关注细节。
简单来说,过程抽象是一种将实现细节隐藏起来,使得代码更加简洁易懂的技巧。
高阶函数使用模式
高阶函数是指能够接收函数作为参数或返回一个函数作为结果的函数。它是一种进阶的过程抽象概念,常用于作为函数装饰器,可以使得代码更加灵活和可重用。
常用高阶函数:
- Once: 一个函数只能被调用一次。
function once(fn) { let called = false; return function () { if (!called) { called = true; fn.apply(this, arguments); } } } let sayHello = once(function () { console.log("Hello!"); }); sayHello(); // "Hello!" sayHello(); // nothing happens - Throttle: 函数被调用时,在一个固定的时间间隔内只会被执行一次。
function throttle(fn, wait) { let lastCall = 0; return function () { let now = Date.now(); if (now - lastCall < wait) { return; } lastCall = now; fn.apply(this, arguments); } } let sayHello = function () { console.log("Hello!"); }; let throttledSayHello = throttle(sayHello, 1000); throttledSayHello(); // "Hello!" throttledSayHello(); // nothing happens setTimeout(throttledSayHello, 2000); // "Hello!" - Debounce: 函数被调用时,在一个固定的时间间隔后才会被执行。
function debounce(fn, wait) { let timeoutId; return function () { clearTimeout(timeoutId); timeoutId = setTimeout(() => { fn.apply(this, arguments); }, wait); } } let sayHello = function () { console.log("Hello!"); }; let debouncedSayHello = debounce(sayHello, 1000); debouncedSayHello(); debouncedSayHello(); setTimeout(debouncedSayHello, 2000); // "Hello!" - Consumer /2: 将两个函数组合成一个新的函数,并将结果传递给第二个函数。
function consumer(fn1, fn2) { return function() { fn2(fn1.apply(this, arguments)); } } let add = (a, b) => a + b; let double = x => x * 2; let addThenDouble = consumer(add, double); console.log(addThenDouble(3,4)); // 14 - Iterative: 将函数应用于数组中的每个元素。
function iterate(arr, fn) { for (let i = 0; i < arr.length; i++) { fn(arr[i]); } } let arr= [1, 2, 3, 4]; let square = x => x * x; iterate(arr, square); // arr is now [1, 4, 9, 16]
这些高阶函数都是常用的设计模式,可以用来实现复杂的功能。它们可以帮助开发人员更好地管理函数的执行次数和时间间隔,从而提高程序的性能。
JavaScript 编程范式
JavaScript 编程范式是指对于编写 JavaScript 代码的方式和风格的统称。
Toggle 是一种常见的功能,用来在两种状态之间切换。
在命令式编程范式中,我们通过操作状态变量来实现 toggle 功能。下面的代码是一个命令式的 toggle 实现:
switcher.onclick = function(evt){
if(evt.target.className === 'on'){
evt.target.className = 'off';
}else{
evt.target.className = 'on';
}
}
在声明式编程范式中,我们通过描述结果而不是如何计算结果来实现 toggle 功能。下面的代码是一个声明式的 toggle 实现:
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'
);
Toggle 三态是指一种可以在三种状态之间切换的 toggle 功能,例如三态开关。可以用命令式或声明式编程范式来实现:
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'
);
总之,命令式编程更侧重于具体操作,而声明式编程更侧重于结果。在不同的场景下应用合适的范式可以使代码更简洁,更易于维护。
三、实践练习例子:
过程抽象
假设我们要编写一个函数,它可以对任意数组进行排序。我们可以使用过程抽象来实现这个函数,而不需要关心数组中具体的元素类型。
function sortArray(arr) {
// 过程抽象:实现了排序算法,但是没有具体实现
// 可以支持任意类型的数组
arr.sort();
return arr;
}
let numbers = [4, 2, 5, 1, 3];
let sortedNumbers = sortArray(numbers);
console.log(sortedNumbers); // [1, 2, 3, 4, 5]
let words = ["dog", "cat", "bird", "ant"];
let sortedWords = sortArray(words);
console.log(sortedWords); // ["ant", "bird", "cat", "dog"]
在这个例子中,我们使用了 JavaScript 的 sort() 方法来实现数组的排序,但是我们并没有详细说明它是如何排序的。这就是过程抽象的一个简单示例,因为我们只关心它能完成排序这个功能,而不关心具体实现细节。
四、课后个人总结:
在学习 JavaScript 编程范式时,我们可以了解到函数式编程适用于纯函数和无副作用的逻辑,声明式编程适用于描述结果。
在学习函数式编程范式时,我们学会了高阶函数的常用使用模式,如Once,Throttle,Debounce,Consumer 和 Iterative 。这些高阶函数都是常用的设计模式,可以用来实现复杂的功能。
最后,在学习状态管理时,我了解了命令式编程范式、声明式编程范式和三态的关系,命令式编程范式可以实现复杂的逻辑,但可能会导致代码难以维护,而声明式编程范式可以使代码更简洁,更易于维护,但可能难以实现复杂的逻辑。三态可以让程序更加灵活,使用命令式或声明式编程范式都可以实现三态。