各司其职
案例:夜间模式切换功能
- 版本一
<header>
<button id="darkModeButton">🌞</button>
<h1>夜间模式切换功能案例</h1>
</header>
<main>
<p>这是网页上夜间模式的一个例子。</p>
</main>
const btn = document.getElementById('darkModeButton');
btn.addEventListener('click', (e) => {
const body = document.body;
if (e.target.innerHTML === '🌞') {
body.style.backgroundColor = 'black';
body.style.color = 'white';
e.target.innerHTML = '🌜'
} else {
body.style.backgroundColor = 'white';
body.style.color = 'black';
e.target.innerHTML = '🌞'
}
});
版本一是通过DOM操作获取ID为darkModeButton的按钮,然后使用addEventListener函数将一个点击事件监听器添加到按钮上。当用户点击按钮时,会在白天模式和夜间模式之间切换页面的背景色和文本颜色,按钮上的图标也会相应地变化,以指示当前的模式。
-
版本二
版本二的 HTML 与版本一的差不多,css代码在版本一的基础上添加以下代码。
body.night {
background-color: #333;
color: #fff;
transition: all 1s;
}
#darkModeButton::after {
content: '🌞';
}
.night #darkModeButton::after {
content: '🌜';
}
const btn = document.getElementById('darkModeButton');
btn.addEventListener('click', (e) => {
const body = document.body;
if (body.className !== 'night') {
body.className = 'night';
} else {
body.className = '';
}
});
版本二 CSS 样式部分中.night 样式定义了夜间模式下页面的背景颜色为深灰色(#333),文本颜色为白色。#darkModeButton::after 定义了按钮的伪元素内容为'🌞',表示白天模式。.night #darkModeButton::after 定义了在夜间模式下按钮的伪元素内容为'🌜',表示夜间模式。JavaScript部分:if (body.className !== 'night') 检查当前页面是否处于夜间模式。className属性用于获取或设置元素的class属性值。如果当前不是夜间模式,则将body元素的class设置为'night',从而应用夜间模式样式。如果当前已经是夜间模式,则将body元素的class设置为空字符串,从而切换回白天模式。
- 版本三
<input type="checkbox" id="modeCheckBox">
<div class="content">
<header>
<label id="darkModeButton" for="modeCheckBox"></label>
<h1>夜间模式切换功能案例</h1>
</header>
<main>
<p>这是网页上夜间模式的一个例子。</p>
</main>
</div>
#modeCheckBox:checked+.content {
background-color: #333;
color: #fff;
transition: all 1s;
}
#darkModeButton::after {
content: '🌞';
}
#modeCheckBox:checked+.content #darkModeButton::after {
content: '🌜';
}
版本三 HTML 样式中#modeCheckBox复选框的id属性与后面的for属性链接了<label>元素。这使得当复选框被选中时,<label>元素就会被激活,从而触发 CSS 样式的应用。CSS 样式中#modeCheckBox:checked + .content样式是一个复合选择器,当#modeCheckBox(复选框)被选中时,后续的.content元素将应用这个样式。在这里,它用于定义夜间模式下的背景颜色和文本颜色。#modeCheckBox:checked + .content #darkModeButton::after样式定义了在夜间模式下按钮的伪元素内容为'🌜',表示夜间模式。
总结
- HTML/CSS/JS各司其职
- 应当避免不必要的有JS直接操作样式
- 可以用 class 来表示状态
- 纯展示类交互寻求零 JS 方案
组件封装
案例:轮播图
- 基本方法
<body>
<div id="my-slider" class="slider-list">
<ul>
<li class="slider-list__item--selected">
<img src="../images/1.jpg" alt="">
</li>
<li class="slider-list__item">
<img src="../images/2.jpg" alt="">
</li>
<li class="slider-list__item">
<img src="../images/3.jpg" alt="">
</li>
<li class="slider-list__item">
<img src="../images/4.jpg" alt="">
</li>
<li class="slider-list__item">
<img src="../images/5.jpg" alt="">
</li>
</ul>
<a class="slider-list__previous"></a>
<a class="slider-list__next"></a>
<div class="slider-list__control">
<span class="slider-list__control-buttons--selected"></span>
<span class="slider-list__control-buttons"></span>
<span class="slider-list__control-buttons"></span>
<span class="slider-list__control-buttons"></span>
<span class="slider-list__control-buttons"></span>
</div>
</div>
</body>
class Slider {
constructor(id, cycle = 3000) {
// 获取轮播图的外部盒子元素和轮播项元素
this.container = document.getElementById(id);
this.items = this.container.querySelectorAll('.slider-list__item, .slider-list__item--selected');
this.cycle = cycle; // 轮播时间间隔,默认为3000毫秒
// 获取圆形控制点的父元素,并添加鼠标移入和移出事件监听
const controller = this.container.querySelector('.slider-list__control');
if (controller) {
const buttons = controller.querySelectorAll(
'.slider-list__control-buttons, .slider-list__control-buttons--selected');
controller.addEventListener('mouseover', evt => {
// 鼠标移入圆形控制点时,获取当前索引并切换至对应图片,并停止自动轮播
const idx = Array.from(buttons).indexOf(evt.target);
if (idx >= 0) {
this.slideTo(idx);
this.stop();
}
});
controller.addEventListener('mouseout', evt => {
// 鼠标移出圆形控制点时,恢复自动轮播
this.start();
});
// 监听slide事件,当切换图片时更新圆形控制点的样式
this.container.addEventListener('slide', evt => {
const idx = evt.detail.index;
const selected = controller.querySelector('.slider-list__control-buttons--selected');
if (selected) selected.className = 'slider-list__control-buttons';
buttons[idx].className = 'slider-list__control-buttons--selected';
});
}
// 获取向前和向后控制按钮的元素,并添加点击事件监听
const previous = this.container.querySelector('.slider-list__previous');
if (previous) {
previous.addEventListener('click', evt => {
// 点击向前按钮时,停止自动轮播,切换至前一张图片,然后恢复自动轮播
this.stop();
this.slidePrevious();
this.start();
evt.preventDefault();
});
}
const next = this.container.querySelector('.slider-list__next');
if (next) {
next.addEventListener('click', evt => {
// 点击向后按钮时,停止自动轮播,切换至下一张图片,然后恢复自动轮播
this.stop();
this.slideNext();
this.start();
evt.preventDefault();
});
}
}
// 获取当前选中的图片项(.slider-list__item--selected)
getSelectedItem() {
let selected = this.container.querySelector('.slider-list__item--selected');
return selected;
}
// 获取当前选中图片项的索引
getSelectedItemIndex() {
return Array.from(this.items).indexOf(this.getSelectedItem());
}
// 切换至指定索引的图片项,通过修改对应项的类名实现切换,并触发自定义的slide事件
slideTo(idx) { // 接收idx参数,表示要滑动到的项的索引
let selected = this.getSelectedItem();
if (selected) {
// 将当前选中的项的类名设为slider-list__item
selected.className = 'slider-list__item';
}
let item = this.items[idx];
if (item) {
// 指定索引的项的类名设为slider-list__item--selected,以显示对应的图片
item.className = 'slider-list__item--selected';
}
const detail = {
index: idx
};
// 触发带有更新的索引信息的自定义事件slide,用于通知其他组件或插件轮播图的变化
const event = new CustomEvent('slide', {
bubbles: true,
detail
});
this.container.dispatchEvent(event);
}
// 切换至下一张图片项,计算下一个索引,并调用slideTo方法实现切换
slideNext() {
let currentIdx = this.getSelectedItemIndex();
let nextIdx = (currentIdx + 1) % this.items.length;
this.slideTo(nextIdx);
}
// 切换至上一张图片项,计算上一个索引,并调用slideTo方法实现切换
slidePrevious() {
let currentIdx = this.getSelectedItemIndex();
let previousIdx = (this.items.length + currentIdx - 1) % this.items.length;
this.slideTo(previousIdx);
}
// 开始自动轮播,使用setInterval定时调用slideNext方法实现自动切换
start() {
this.stop();
this._timer = setInterval(() => this.slideNext(), this.cycle);
}
// 停止自动轮播,清除之前设置的定时器,即clearInterval
stop() {
clearInterval(this._timer);
}
}
// 创建Slider实例并开始自动轮播
const slider = new Slider('my-slider');
// 启动自动轮播功能
slider.start();
代码中实现了轮播图的功能,包括鼠标悬停暂停、点击控制按钮切换图片以及自动轮播功能。
- 重构:插件化
html代码与基本方法中的一致
// 定义 Slider类,用于管理图片轮播图的功能
class Slider {
// 在构造函数中接受两个参数:id和cycle
// id表示包含轮播图的容器元素的ID,而cycle表示自动轮播功能的时间间隔(以毫秒为单位)
constructor(id, cycle = 3000) {
// 通过提供的id选择了轮播图的容器元素以及轮播图项的列表
this.container = document.getElementById(id);
this.items = this.container.querySelectorAll('.slider-list__item, .slider-list__item--selected');
this.cycle = cycle;
}
// registerPlugins方法允许注册不同的插件来扩展轮播图的功能,
registerPlugins(...plugins) {
plugins.forEach(plugin => plugin(this));
}
getSelectedItem() {
const selected = this.container.querySelector('.slider-list__item--selected');
return selected;
}
getSelectedItemIndex() {
return Array.from(this.items).indexOf(this.getSelectedItem());
}
slideTo(idx) {
const selected = this.getSelectedItem();
if (selected) {
selected.className = 'slider-list__item';
}
const item = this.items[idx];
if (item) {
item.className = 'slider-list__item--selected';
}
const detail = {
index: idx
};
const event = new CustomEvent('slide', {
bubbles: true,
detail
});
this.container.dispatchEvent(event);
}
slideNext() {
const currentIdx = this.getSelectedItemIndex();
const nextIdx = (currentIdx + 1) % this.items.length;
this.slideTo(nextIdx);
}
slidePrevious() {
const currentIdx = this.getSelectedItemIndex();
const previousIdx = (this.items.length + currentIdx - 1) % this.items.length;
this.slideTo(previousIdx);
}
// 用于为轮播图的容器元素添加事件监听器
addEventListener(type, handler) {
this.container.addEventListener(type, handler);
}
start() {
this.stop();
this._timer = setInterval(() => this.slideNext(), this.cycle);
}
stop() {
clearInterval(this._timer);
}
}
// pluginController插件函数处理轮播图的控制按钮
function pluginController(slider) {
const controller = slider.container.querySelector('.slider-list__control');
if (controller) {
const buttons = controller.querySelectorAll('.slider-list__control-buttons, .slider-list__control-buttons--selected');
// 监听控制按钮的mouseover和mouseout事件来触发轮播切换和停止/开始自动轮播
controller.addEventListener('mouseover', evt => {
const idx = Array.from(buttons).indexOf(evt.target);
if (idx >= 0) {
slider.slideTo(idx);
slider.stop();
}
});
controller.addEventListener('mouseout', evt => {
slider.start();
});
// 当发生轮播切换时,更新控制按钮的类名
slider.addEventListener('slide', evt => {
const idx = evt.detail.index;
const selected = controller.querySelector('.slider-list__control-buttons--selected');
if (selected) selected.className = 'slider-list__control-buttons';
buttons[idx].className = 'slider-list__control-buttons--selected';
});
}
}
// pluginPrevious插件函数处理轮播图的"上一个"按钮
function pluginPrevious(slider) {
const previous = slider.container.querySelector('.slider-list__previous');
if (previous) {
previous.addEventListener('click', evt => {
slider.stop();
slider.slidePrevious();
slider.start();
evt.preventDefault();
});
}
}
// pluginNext插件函数处理轮播图的"下一个"按钮
function pluginNext(slider) {
const next = slider.container.querySelector('.slider-list__next');
if (next) {
next.addEventListener('click', evt => {
slider.stop();
slider.slideNext();
slider.start();
evt.preventDefault();
});
}
}
const slider = new Slider('my-slider');
// 注册插件函数
slider.registerPlugins(pluginController, pluginPrevious, pluginNext);
slider.start();
代码中定义了一个Slider类,用于管理图片轮播图的功能。它允许滑动到特定的图片、自动轮播功能以及注册插件来扩展轮播图的行为。提供的插件添加了控制按钮、上一个和下一个按钮,以及一个随机切换图片的按钮。
- 重构:模板化
<body>
<div id="my-slider" class="slider-list"></div>
</body>
class Slider {
constructor(id, opts = {
// opts是一个包含图片数组images
images: [],
cycle: 3000
}) {
this.container = document.getElementById(id);
this.options = opts;
// 使用提供的images和render方法来创建轮播图的初始HTML结构,将生成的HTML字符串插入到轮播图容器中
this.container.innerHTML = this.render();
this.cycle = opts.cycle || 3000;
// 选择轮播项的元素,并将选中的项初始化为第一张图片
this.items = this.container.querySelectorAll('.slider-list__item, .slider-list__item--selected');
this.slideTo(0);
}
// render方法用于将图片数组渲染成轮播图的HTML内容,并返回一个字符串表示图片列表
render() {
const images = this.options.images;
const content = images.map(image => `
<li class="slider-list__item">
<img src="${image}"/>
</li>
`.trim());
return `<ul>${content.join('')}</ul>`;
}
// 注册插件来扩展轮播图的功能
registerPlugins(...plugins) {
plugins.forEach(plugin => {
// 为每个插件创建一个包含插件内容的div元素,并将其插入到轮播图容器中
const pluginContainer = document.createElement('div');
pluginContainer.className = 'slider-list__plugin';
pluginContainer.innerHTML = plugin.render(this.options.images);
this.container.appendChild(pluginContainer);
// 调用action方法将所需的功能添加到轮播图
plugin.action(this);
});
}
getSelectedItem() {
let selected = this.container.querySelector('.slider-list__item--selected');
return selected;
}
getSelectedItemIndex() {
return Array.from(this.items).indexOf(this.getSelectedItem());
}
slideTo(idx) {
let selected = this.getSelectedItem();
if (selected) {
selected.className = 'slider-list__item';
}
let item = this.items[idx];
if (item) {
item.className = 'slider-list__item--selected';
}
const detail = {
index: idx
};
const event = new CustomEvent('slide', {
bubbles: true,
detail
});
this.container.dispatchEvent(event);
}
slideNext() {
const currentIdx = this.getSelectedItemIndex();
const nextIdx = (currentIdx + 1) % this.items.length;
this.slideTo(nextIdx);
}
slidePrevious() {
const currentIdx = this.getSelectedItemIndex();
const previousIdx = (this.items.length + currentIdx - 1) % this.items.length;
this.slideTo(previousIdx);
}
addEventListener(type, handler) {
this.container.addEventListener(type, handler);
}
start() {
this.stop();
this._timer = setInterval(() => this.slideNext(), this.cycle);
}
stop() {
clearInterval(this._timer);
}
}
// pluginController对象,其中包含了渲染轮播图控制按钮的render方法和处理控制按钮功能的action方法
const pluginController = {
// render方法根据图片数组images,为每个图片创建一个控制按钮,并为第一张图片添加选中状态
render(images) {
return `
<div class="slider-list__control">
${images.map((image, i) => `
<span class="slider-list__control-buttons${i===0?'--selected':''}"></span>
`).join('')}
</div>
`.trim();
},
// action方法添加了控制按钮的交互功能,包括鼠标悬停时切换到对应图片和自动轮播的停止/开始
action(slider) {
const controller = slider.container.querySelector('.slider-list__control');
if (controller) {
const buttons = controller.querySelectorAll('.slider-list__control-buttons, .slider-list__control-buttons--selected');
controller.addEventListener('mouseover', evt => {
const idx = Array.from(buttons).indexOf(evt.target);
if (idx >= 0) {
slider.slideTo(idx);
slider.stop();
}
});
controller.addEventListener('mouseout', evt => {
slider.start();
});
slider.addEventListener('slide', evt => {
const idx = evt.detail.index;
const selected = controller.querySelector('.slider-list__control-buttons--selected');
if (selected) selected.className = 'slider-list__control-buttons';
buttons[idx].className = 'slider-list__control-buttons--selected';
});
}
}
};
// pluginPrevious对象,它包含了渲染"上一个"按钮的render方法和处理"上一个"按钮功能的action方法
const pluginPrevious = {
render() {
return `<a class="slider-list__previous"></a>`;
},
action(slider) {
const previous = slider.container.querySelector('.slider-list__previous');
if (previous) {
previous.addEventListener('click', evt => {
slider.stop();
slider.slidePrevious();
slider.start();
evt.preventDefault();
});
}
}
};
// pluginNext是一个对象,它包含了渲染"下一个"按钮的render方法和处理"下一个"按钮功能的action方法
const pluginNext = {
render() {
return `<a class="slider-list__next"></a>`;
},
action(slider) {
const next = slider.container.querySelector('.slider-list__next');
if (next) {
next.addEventListener('click', evt => {
slider.stop();
slider.slideNext();
slider.start();
evt.preventDefault();
});
}
}
};
const slider = new Slider('my-slider', {
// 传递包含图片数组和自动轮播时间的对象
images: ['../images/1.jpg', '../images/2.jpg', '../images/3.jpg', '../images/4.jpg', '../images/5.jpg'],
cycle: 3000
});
slider.registerPlugins(pluginController, pluginPrevious, pluginNext);
slider.start();
代码中定义了一个Slider类,用于管理图片轮播图的功能。它可以滑动到指定的图片,还可以自动轮播,并通过注册插件来添加额外的功能,如控制按钮和前后切换按钮。插件对象提供了render方法用于渲染HTML内容和action方法用于添加功能。整体结构更加灵活和易于扩展。
- 重构:组件框架
html代码与模板化中的一致
// 定义Component类,它作为轮播图组件的基类
class Component {
constructor(id, opts = {name, data: []}) {
this.container = document.getElementById(id);
this.options = opts;
this.container.innerHTML = this.render(opts.data);
}
registerPlugins(...plugins) {
plugins.forEach(plugin => {
const pluginContainer = document.createElement('div');
pluginContainer.className = `${name}__plugin`;
pluginContainer.innerHTML = plugin.render(this.options.data);
this.container.appendChild(pluginContainer);
plugin.action(this);
});
}
// 抽象方法
render(data) {
return '';
}
}
// 定义Slider类,它继承自Component类,用于实现图片轮播功能
class Slider extends Component {
constructor(id, opts = {name: 'slider-list', data: [], cycle: 3000}) {
super(id, opts);
this.items = this.container.querySelectorAll('.slider-list__item, .slider-list__item--selected')
this.cycle = opts.cycle || 3000;
this.slideTo(0);
}
// 重写了基类的render方法
render(data) {
// 根据传入的图片数据data,生成轮播图中的图片<li>元素
const content = data.map(image => `
<li class="slider-list__item">
<img src="${image}"/>
</li>
`.trim());
return `<ul>${content.join('')}</ul>`;
}
getSelectedItem() {
let selected = this.container.querySelector('.slider-list__item--selected');
return selected;
}
getSelectedItemIndex() {
return Array.from(this.items).indexOf(this.getSelectedItem());
}
slideTo(idx) {
const selected = this.getSelectedItem();
if (selected) {
selected.className = 'slider-list__item';
}
let item = this.items[idx];
if (item) {
item.className = 'slider-list__item--selected';
}
const detail = {
index: idx
};
const event = new CustomEvent('slide', {bubbles: true, detail});
this.container.dispatchEvent(event);
}
slideNext() {
const currentIdx = this.getSelectedItemIndex();
const nextIdx = (currentIdx + 1) % this.items.length;
this.slideTo(nextIdx);
}
slidePrevious() {
const currentIdx = this.getSelectedItemIndex();
const previousIdx = (this.items.length + currentIdx - 1) % this.items.length;
this.slideTo(previousIdx);
}
addEventListener(type, handler) {
this.container.addEventListener(type, handler);
}
start() {
this.stop();
this._timer = setInterval(() => this.slideNext(), this.cycle);
}
stop() {
clearInterval(this._timer);
}
}
const pluginController = {
render(images) {
return `
<div class="slider-list__control">
${images.map((image, i) => `
<span class="slider-list__control-buttons${i===0?'--selected':''}"></span>
`).join('')}
</div>
`.trim();
},
action(slider) {
let controller = slider.container.querySelector('.slider-list__control');
if (controller) {
let buttons = controller.querySelectorAll('.slider-list__control-buttons, .slider-list__control-buttons--selected');
controller.addEventListener('mouseover', evt => {
const idx = Array.from(buttons).indexOf(evt.target);
if (idx >= 0) {
slider.slideTo(idx);
slider.stop();
}
});
controller.addEventListener('mouseout', evt => {
slider.start();
});
slider.addEventListener('slide', evt => {
const idx = evt.detail.index;
let selected = controller.querySelector('.slider-list__control-buttons--selected');
if (selected) selected.className = 'slider-list__control-buttons';
buttons[idx].className = 'slider-list__control-buttons--selected';
});
}
}
};
const pluginPrevious = {
render() {
return `<a class="slider-list__previous"></a>`;
},
action(slider) {
const previous = slider.container.querySelector('.slider-list__previous');
if (previous) {
previous.addEventListener('click', evt => {
slider.stop();
slider.slidePrevious();
slider.start();
evt.preventDefault();
});
}
}
};
const pluginNext = {
render() {
return `<a class="slider-list__next"></a>`;
},
action(slider) {
const next = slider.container.querySelector('.slider-list__next');
if (next) {
next.addEventListener('click', evt => {
slider.stop();
slider.slideNext();
slider.start();
evt.preventDefault();
});
}
}
};
const slider = new Slider('my-slider', {
// 传递包含图片数组、组件名称和自动轮播时间的对象
name: 'slider-list',
data: ['../images/1.jpg', '../images/2.jpg', '../images/3.jpg', '../images/4.jpg', '../images/5.jpg'],
cycle: 3000
});
slider.registerPlugins(pluginController, pluginPrevious, pluginNext);
slider.start();
代码中定义了一个基于组件框架的图片轮播组件。它提供了扩展性和灵活性,通过继承和重写方法来实现不同功能。组件可以根据传入的数据渲染HTML内容,并可以通过注册插件来添加不同的功能,如控制按钮和前后切换按钮。最终创建一个轮播图实例,并注册相应插件来实现图片轮播功能。
总结:
- 组件设计原则:封装性、正确性、扩展性、复用性
- 实现组件的步骤:结构设计、展现效果、行为设计
- 三次重构:插件化、模板化、抽象化(组件框架)
过程抽象
1. 高阶函数
高阶函数是指能够接受其他函数作为参数或者返回一个函数的函数。这种特性让JavaScript可以更灵活和功能强大。高阶函数的应用可以使代码更简洁、可读性更高,并且有助于提高代码的复用性和扩展性。
常用高阶函数:
- Once()
Once 函数用于创建一个只能执行一次的函数。多次调用这个函数,只会返回第一次执行时的结果,后续调用都将被忽略。这在某些情况下很有用,比如只需要执行某个操作一次,例如执行初始化代码或者只需要加载资源一次。
- Throttle()-节流函数
Throttle 函数用于控制在一段时间内,只执行一次函数调用。它可以用于限制频繁触发的事件的执行次数,比如滚动事件、鼠标移动事件等。这样可以避免事件处理函数过于频繁地执行,提高性能和减少资源消耗。
- Debounce()-防抖函数
Debounce 函数用于在一连续的事件中,只执行最后一次函数调用。当频繁触发事件时,它将等待一定的延迟时间,如果在这段延迟时间内再次触发了事件,之前的调用将被取消,只会执行最后一次调用。处理搜索输入框的输入事件时非常有用,可以避免频繁地进行搜索操作。
- Consumer()
Consumer 函数接受两个函数作为参数,并返回一个新函数。这个新函数会将第一个函数的输出作为第二个函数的输入,并执行第二个函数。这个函数组合方式可以用于将两个功能独立的函数组合在一起,实现更复杂的逻辑。
- Iterative()
Iterative 函数是一个迭代器函数,用于对数据集合进行迭代和处理。它可以帮助我们更方便地遍历数组、对象等数据结构,进行处理或者进行条件判断。在 JavaScript 中,可以使用 for...of 循环或者 forEach 方法进行迭代处理。
使用高阶函数的好处:
- 代码复用和模块化:高阶函数可以帮助将一些通用的功能封装起来,使得这些功能可以在不同的地方重复使用,从而实现代码的复用和模块化。
- 代码简洁和可读性:通过使用高阶函数,可以将复杂的逻辑简化成一个函数调用,使代码更加简洁和易于阅读,减少了冗余代码的存在。
- 抽象和解耦:高阶函数可以将具体的实现细节抽象出来,使得函数的调用方不需要关心具体的实现细节,从而实现解耦。
- 灵活性和可扩展性:高阶函数可以接受其他函数作为参数或返回一个函数,这样可以使代码更加灵活和可扩展。通过传递不同的函数作为参数,可以实现不同的功能。
- 函数组合和管道:高阶函数可以用于将多个函数组合在一起,形成函数管道,从而实现复杂的功能。
- 错误处理和容错机制:通过在高阶函数中处理错误和异常,可以增加代码的健壮性和容错能力。
- 异步编程:高阶函数在处理异步编程中也非常有用,例如使用回调函数、Promise、async/await等。
2. 编程范式
编程范式是一种编程方式,它描述了程序员在编写代码时所采用的思维方式和方法。主要的编程范式包括命令式编程语言和声明式编程语言。
命令式编程语言:
- 命令式编程语言是最常见和传统的编程范式。在命令式编程中,程序员编写一系列的指令,描述计算机执行的具体步骤和操作。程序员需要显式地指定计算机执行的每一个细节,包括控制流程、数据的处理和状态的变化等。
- 这种编程方式更接近计算机的底层操作,对硬件进行直接操作。常见的命令式编程语言包括 C、C++、Java 和 Python(在一定程度上也支持声明式编程)等。
声明式编程语言:
- 声明式编程语言更加注重描述问题的本质和所需的结果,而不是直接指定计算机执行的步骤。程序员将问题的逻辑和需求表达为一系列的声明,而不需要关注具体的执行细节。
- 声明式编程语言更加抽象和高级,它们更关注问题的本质和解决方案,而不是计算机执行的步骤。这使得代码更加简洁、清晰和易于理解。
- 常见的声明式编程语言包括 SQL(用于数据库查询)、HTML(用于网页布局)、CSS(用于样式定义)、JavaScript中的一些函数式编程特性(如map、filter、reduce等)等。
如何区分命令式的编程语言和声明式编程语言:
-
控制流程:
- 命令式编程语言需要显式地定义程序的控制流程,包括循环、条件语句等,以指定计算机执行的具体步骤。
- 声明式编程语言则更关注问题的本质和所需的结果,不需要直接指定计算机的执行步骤,而是通过声明来表达需求。
-
数据处理:
- 在命令式编程语言中,程序员需要显式地处理数据和状态的变化。需要通过变量和数据结构来跟踪和修改数据。
- 声明式编程语言更关注问题的描述,通常通过函数式编程或查询语言来进行数据处理和变换。
-
代码抽象:
- 在命令式编程中,代码通常是以指令和步骤的形式来表达,较为具体,更注重细节。
- 声明式编程更注重问题的抽象和表达,通过高级的抽象方式来表达问题的本质,减少了对细节的关注。
-
可读性:
- 由于命令式编程需要显式地描述步骤和细节,代码可能会比较冗长,可读性稍差一些。
- 声明式编程的代码通常更加简洁,表达更为清晰,易于阅读和理解。
-
编程风格:
- 命令式编程强调通过指令来控制计算机执行的步骤,类似于给计算机下达命令。
- 声明式编程强调通过声明来描述问题的本质和所需的结果,更加抽象和高级。
本篇笔记为个人总结,学习交流使用,欢迎各位大佬评价指正,非常感谢!