### JS复习练习
- 
1. 任务1:创建一个简单的问候函数
- 编写一个函数greet,接受一个名字作为参数,并返回一个问候语,例如:“Hello, [名字]! Welcome to JavaScript.”。
```js
function greet(name){
return `Hello,${name}! Welcome to JavaScript`
}
console.log('===============创建简单的问候函数 =================');
console.log(greet('李华'));
```
2. 任务2:计算数组的平均值
- 编写一个函数calculateAverage,接受一个数字数组作为参数,并返回数组的平均值。
```js
function calculateAverage(arr) {
let sum = 0
arr.forEach(x => {
sum += x
});
let ave = sum / arr.length
return ave;
}
console.log('===============计算数组的平均值 =================');
console.log(calculateAverage([1,2,3,4,5]))
// 第二种方法【reduce】
function calculateAverage02(array) {
const sum = array.reduce((x,y) => (x + y),0) /array.length
return sum
}
console.log(calculateAverage02([1,2,3,4,5]));
```
3. 任务3:检查字符串是否为回文
- 编写一个函数isPalindrome,接受一个字符串作为参数,判断该字符串是否为回文(正读和反读相同)。
```js
function isPalindrome(Str){
// 清理字符串,都变成小写,不要空字符 【 .toLowerCase(); 】
const One = Str.replace(/[^a-zA-Z0-9]/g,'').toLowerCase() // g 代表全局匹配,如果没有的话,默认为查找第一个字符
// 反读 【split()把字符串拆分成数组】【reverse()反转】【join('')把数组重新拼接成字符串】
const Two = One.split('').reverse().join('')
if (One === Two) {
console.log('是回文');
}
else{
console.log('不是回文');
}
}
console.log('===============检查字符串是否为回文 =================');
isPalindrome('alrla')
isPalindrome('abcd')
```
4. 任务4:实现一个简单的计数器
- 使用闭包实现一个简单的计数器,每次调用时返回当前的计数值。
```js
// 闭包:让内部函数能够访问并修改外部函数的作用域中的变量
// 定义一个外部函数
function A(){
let number = 0
// AA 函数的参数 number 不能与外部变量同名,会导致作用域冲突。
// 去掉参数后,AA 函数可以直接访问和修改外部的 number,从而实现闭包的效果。
function AA(){
number ++
// 返回当前值
return number
}
// 返回内部函数的值,让外部可以调用
return AA;
}
console.log('===============闭包=================');
const counts = A()
console.log(counts());
console.log(counts());
console.log(counts());
```
5. 任务5:过滤数组中的偶数
- 编写一个函数filterEvenNumbers,接受一个数字数组作为参数,返回一个只包含偶数的新数组。
```js
function filterEvenNumbers(ArrayList) {
console.log("==============过滤数组中的偶数 =================");
const NewAL = ArrayList.filter(item => item % 2 ==0 )
console.log(NewAL);
}
filterEvenNumbers([1,2,3,4,5,6]);
```
6. 任务6:实现一个简单的对象工厂
- 编写一个函数createPerson,接受name和age作为参数,返回一个包含这些属性的对象。
```js
function createPerson(Name,Age) {
const Obj = {Name,Age}
return Obj
}
console.log("============== 简单的对象工厂 =================");
console.log(createPerson('翠花',18));
```
7. 任务7:递归计算阶乘
- 编写一个递归函数factorial,计算一个非负整数的阶乘。
```js
// 阶乘的定义是:
// n!=n×(n−1)×(n−2)×⋯×1
// 0!=1
function factorial(Num){
if (Num == 0) {
return 1
}
else{
// factorial(Num-1) 是一个递归调用,而不是直接的数值。它的作用是计算 Num-1 的阶乘,然后将结果乘以当前的 Num。
return Num * factorial(Num-1)
}
}
function factorial02(Num){
// 【三元运算符】 条件表达式 ? 表达式1 : 表达式2
return Num == 0 ? 1 : Num * factorial02(Num - 1)
}
console.log("============== 递归计算阶乘 =================");
console.log(factorial(4));
console.log(factorial02(4));
```
8. 任务8:实现一个简单的事件监听器
- 编写一个函数addEventListener,模拟HTML元素的事件监听器功能。接受一个事件类型和一个回调函数作为参数,并在触发时调用回调函数。
```js
console.log("============== 事件监听器 =================");
function addEventListene(event,callback){
function even(){
console.log(`这个${event}被触发了`);
callback()
}
even()
}
addEventListene('click',function(){})
console.log("============== 实现简单的模块 =================");
```
9. 任务9:实现一个简单的模块
- 使用模块模式封装一个mathUtils模块,包含add和multiply两个函数
```js
const mathUtils = (function(){
function add(a,b){
return a+b
}
function multiply(a,b){
return a*b
}
return{add,multiply}
})()
console.log(mathUtils.add(1,2));
console.log(mathUtils.multiply(1,2));
console.log("============== 实现Promise =================");
```
10. 任务9:实现一个简单的Promise
- 使用Promise实现一个异步函数fetchData,模拟从服务器获取数据。如果成功,返回一个字符串;如果失败,抛出一个错误。
```js
function fetchData(){
return new Promise((resolve,reject)=>{
const aa = true
if (aa) {
resolve('获取成功');
}
else{
reject(new Error('获取失败'))
}
})
}
fetchData().then(x=>console.log(x))
```
### 创建完整nodejs项目
- package.json
```json
{
"name":"Demo01",
"main": "app.js",
"scripts": {
"rr":"node app.js"
},
"dependencies": {
"koa":"latest"
}
}
```
- npm i 安装依赖
- npm run rr 跑起来
- 
### CommonJS 与 ES Modules 的区别及常规用法
1. CommonJS:是一种模块化规范,主要用于 Node.js 环境。它通过 require 和 module.exports 实现模块的导入和导出。
- 代码
```js
导出模块
// setting.js
function fn() {
console.log('我是CommonJS');
}
function fn01() {
console.log('我尝试一下');
}
module.exports = { fn, fn01 };
导入模块
// app.js
const abc = require('./setting');
abc.fn(); // 输出: 我是CommonJS
abc.fn01(); // 输出: 我尝试一下
```
2. ES Modules:是 JavaScript 的原生模块化规范,适用于浏览器和 Node.js(需配置支持)。它通过 import 和 export 实现模块的导入和导出。
- 支持动态导入:通过 import() 返回一个 Promise,支持按需加载。
- (需配置 "type": "module" 或使用 .mjs 文件扩展名)。
- 代码
```js
导出模块
// abc.mjs
export function fnA() {
console.log('我是ES');
}
export const arr = [1, 2, 3, 4, 5, 6];
导入模块
// app.mjs
let abc = await import ('./abc.mjs')
abc.fnA() // 输出: 我是ES
console.log(abc.arr) // 输出: [1, 2, 3, 4, 5, 6]
```
#### CommonJS 与 ES Modules 的区别
| 特性 | CommonJS | ES Modules |
|------------------|-----------------------------------------------|-------------------------------------------------|
| **加载方式** | 同步加载,运行时解析依赖 | 静态分析,编译时解析依赖 |
| **导入语法** | 使用 `require()` | 使用 `import` 和 `export` |
| **动态加载支持** | 不支持 | 支持(通过 `import()`) |
| **运行时性能** | 稍低(动态解析) | 较高(静态优化) |
| **作用域** | 模块私有作用域,模块导出的内容会被缓存 | 导入的是活的绑定,模块内部值变化会反映到导入处 |
| **适用环境** | 主要用于 Node.js | 适用于浏览器和 Node.js |
| **文件扩展名** | 默认 `.js` | 需 `.mjs` 或配置 `"type": "module"` |
## 注意事项
### 文件扩展名
- 如果使用 ES Modules,文件扩展名需为 `.mjs`,或在 `package.json` 中配置 `"type": "module"`。
- CommonJS 默认使用 `.js` 扩展名。
### 运行环境
- **CommonJS** 是 Node.js 的传统模块系统,适合服务器端开发。
- **ES Modules** 是现代 JavaScript 的模块化标准,适用于浏览器和 Node.js,支持静态分析和动态导入。