js深入学习
1.for和forEach遍历
在真实的开发中,for
循环和 forEach
各有优缺点,选择哪一种取决于具体的使用场景。以下是两者的比较:
1. forEach
:简洁、适合不可中断的遍历
优点:
简洁易读:代码更简洁,特别适合对数组、
NodeList
等可迭代对象的遍历。避免手动处理索引:
forEach
直接传递当前元素和索引,省去了手动处理计数器的麻烦。
缺点:
无法中途退出:
forEach
无法通过break
或return
来中途退出循环,除非抛出异常。可能不适合性能关键的代码:
forEach
虽然易读,但在某些性能要求非常高的场景中,for
可能更高效。
适用场景:
遍历时不需要中途退出。
不关心性能上的微小差异。
代码可读性高于性能优先的场景。
2. for
:灵活、适合复杂场景
优点:
更灵活:可以完全控制循环的条件、步长等,支持
break
、continue
等控制流操作。更适合性能要求高的场景:在处理大量数据时,
for
循环可能比forEach
更高效,特别是在需要频繁操作数组索引的场景。可以根据需求从某个索引开始、倒序循环等,控制力更强。
缺点:
相对繁琐:相比
forEach
,需要手动维护循环变量、步进操作,增加了代码的复杂性。
适用场景:
需要中途退出循环的场景(例如找到一个匹配的值后停止)。
性能关键的场景,或对性能优化有更高要求时。
需要对数组的索引进行更多控制或使用复杂逻辑。
总结
日常开发中:
forEach
更加简洁和易读,适合绝大多数场景。特殊需求或性能关键场景:如果需要控制循环的中断、倒序或复杂的条件判断,
for
循环会更合适。
2.currentTarget
和 target
1. target
定义:
target
是触发事件的元素,也就是用户实际点击或触发事件的那个元素。特性: 即使事件在冒泡过程中被父级元素捕获,
target
依然指向最初触发事件的子元素
2. currentTarget
定义:
currentTarget
是事件处理程序绑定的元素,指的是当前处理事件的那个元素。特性: 无论事件是在哪里触发的,
currentTarget
都指向绑定了当前事件处理程序的元素。
<div id="parent">
<button id="child">点击我</button>
</div>
<script>
const parent = document.querySelector('#parent');
parent.addEventListener('click', (event) => {
console.log('target:', event.target); // 输出:<button id="child">
console.log('currentTarget:', event.currentTarget); // 输出:<div id="parent">
});
</script>
3.Axios
1. 安装 Axios
如果你在项目中使用 npm,可以通过以下命令安装 Axios:
npm install axios
2. 导入 Axios
在你的 JavaScript 文件中导入 Axios:
import axios from 'axios';
3. 发送 GET 请求
发送 GET 请求来获取数据:
axios.get('https://api.example.com/data')
.then(response => {
console.log(response.data); // 处理成功的响应数据
})
.catch(error => {
console.error('Error fetching data:', error); // 处理错误
});
4. 发送 POST 请求
发送 POST 请求来提交数据:
axios.post('https://api.example.com/data', {
name: 'John Doe',
age: 30
})
.then(response => {
console.log('Data submitted successfully:', response.data);
})
.catch(error => {
console.error('Error submitting data:', error);
});
5. 设置请求头
可以设置自定义请求头,例如发送 JSON 数据:
axios.post('https://api.example.com/data', {
name: 'John Doe',
age: 30
}, {
headers: {
'Content-Type': 'application/json'
}
})
.then(response => {
console.log('Data submitted successfully:', response.data);
})
.catch(error => {
console.error('Error submitting data:', error);
});
6. 使用 async/await
使用 async/await 使代码更简洁:
async function fetchData() {
try {
const response = await axios.get('https://api.example.com/data');
console.log(response.data);
} catch (error) {
console.error('Error fetching data:', error);
}
}
fetchData();
7. 处理请求和响应拦截器
可以在请求发送之前或响应到达之前进行拦截处理:
axios.interceptors.request.use(config => {
// 在请求发送之前做些什么
console.log('Request sent:', config);
return config;
}, error => {
// 处理请求错误
return Promise.reject(error);
});
axios.interceptors.response.use(response => {
// 处理响应数据
console.log('Response received:', response);
return response;
}, error => {
// 处理响应错误
return Promise.reject(error);
});
8. 取消请求
可以使用 Axios 的取消令牌来取消请求:
const CancelToken = axios.CancelToken;
let cancel;
axios.get('https://api.example.com/data', {
cancelToken: new CancelToken(function executor(c) {
cancel = c;
})
})
.then(response => {
console.log(response.data);
})
.catch(error => {
if (axios.isCancel(error)) {
console.log('Request canceled:', error.message);
} else {
console.error('Error fetching data:', error);
}
});
// 取消请求
cancel('Operation canceled by the user.');
9. 并发请求
可以使用 axios.all
和 axios.spread
来处理并发请求:
axios.all([
axios.get('https://api.example.com/data1'),
axios.get('https://api.example.com/data2')
])
.then(axios.spread((response1, response2) => {
console.log('Data from first request:', response1.data);
console.log('Data from second request:', response2.data);
}))
.catch(error => {
console.error('Error with concurrent requests:', error);
});
4.异步编程
1. 回调函数(Callback)
回调函数是将一个函数作为参数传递给另一个函数,当任务完成后调用这个回调函数。
例子:
function fetchData(callback) {
setTimeout(() => {
console.log("数据已获取");
callback("这是数据");
}, 1000); // 模拟1秒后获取数据
}
fetchData((data) => {
console.log("回调函数处理数据: " + data);
});
解释:
setTimeout
模拟一个异步操作(如获取数据)。当数据获取完成后,回调函数被调用,传递数据并执行。
2. Promises
Promise
对象表示异步操作的最终完成(或失败)及其结果的值。它可以链式处理,避免 "回调地狱"。
例子:
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const success = true; // 模拟成功或失败
if (success) {
resolve("成功获取数据");
} else {
reject("数据获取失败");
}
}, 1000);
});
}
fetchData()
.then(data => console.log("Promise 成功: " + data))
.catch(error => console.log("Promise 失败: " + error));
解释:
resolve
表示操作成功并返回数据,reject
表示操作失败。使用
.then()
处理成功,.catch()
处理失败。
3. async/await
async/await
是基于 Promise
的语法糖,使异步代码更像同步代码,易于阅读和理解。
例子:
function fetchData() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("成功获取数据");
}, 1000);
});
}
async function getData() {
try {
const data = await fetchData();
console.log("Async/Await 获取数据: " + data);
} catch (error) {
console.log("Async/Await 出错: " + error);
}
}
getData();
解释:
async
函数返回一个Promise
。await
会暂停代码执行,直到Promise
完成后继续,简化了.then()
的链式调用。
5.express框架
Express 和 Node.js 的对比与优点:
更简化的路由管理:
在纯 Node.js 中,你需要手动处理路由,并解析请求 URL 和 HTTP 方法。而 Express 通过简单的路由定义方法,如
app.get()
、app.post()
等,让路由更加直观易读。
Node.js 原生路由:
const http = require('http'); http.createServer((req, res) => { if (req.url === '/' && req.method === 'GET') { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Home Page'); } else if (req.url === '/about' && req.method === 'GET') { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('About Page'); } }).listen(3000);
Express 路由:
const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send('Home Page'); }); app.get('/about', (req, res) => { res.send('About Page'); }); app.listen(3000);
优点:Express 路由更简洁、结构化,易于维护。
内置中间件支持:
Express 提供丰富的中间件支持,用于处理请求体(如
express.json()
)、静态文件、日志记录等。在 Node.js 中,处理这些任务需要手动编写代码或依赖多个库,而 Express 提供了现成的中间件,减少重复工作。
Express 中处理 JSON 请求:
app.use(express.json()); app.post('/data', (req, res) => { console.log(req.body); // 自动解析 JSON res.send('Data received'); });
优点:Express 中间件让处理常见任务变得非常简单。
简化的错误处理:
在 Node.js 中,处理错误通常需要在每个请求和响应处理程序中编写额外的逻辑。而 Express 提供了一个统一的错误处理中间件,使处理和捕获错误更加高效。
Express 错误处理中间件:
app.use((err, req, res, next) => { console.error(err.stack); res.status(500).send('Something broke!'); });
优点:集中式的错误处理让代码更整洁。
模块化开发:
Express 强调模块化开发,可以轻松地将路由和中间件拆分为独立的模块。这使得代码结构更清晰,适合构建大型应用。
Node.js 模块管理较为原始,需要自己构建架构,Express 提供的
Router
模块可以让你轻松拆分路由逻辑:const router = express.Router(); router.get('/users', (req, res) => { res.send('User list'); }); module.exports = router;
Express 提供了基于 Node.js 的开发框架,让你更加专注于应用的业务逻辑,而不用处理底层的繁琐任务。其优点包括简化路由管理、内置中间件支持、集中的错误处理以及更模块化的开发模式。相比之下,使用纯 Node.js 开发会更加繁琐,尤其是在处理复杂的 HTTP 服务器或 API 时。