1107 lines
26 KiB
Markdown
1107 lines
26 KiB
Markdown
# 1. JavaScript
|
||
|
||
## 1.1 基础语法
|
||
|
||
### 1.1.1 变量声明
|
||
JavaScript 中可以使用 `var`、`let` 和 `const` 来声明变量。示例如下:
|
||
```javascript
|
||
// 使用 var 声明变量
|
||
var oldVariable = 'This is a var variable';
|
||
|
||
// 使用 let 声明变量
|
||
let newVariable = 'This is a let variable';
|
||
|
||
// 使用 const 声明常量
|
||
const constantValue = 'This is a constant';
|
||
```
|
||
|
||
### 1.1.2 数据类型
|
||
JavaScript 有七种基本数据类型:`undefined`、`null`、`boolean`、`number`、`string`、`symbol` 和 `bigint`,以及一种引用数据类型 `object`。示例如下:
|
||
```javascript
|
||
// undefined
|
||
let undef;
|
||
console.log(undef); // undefined
|
||
|
||
// null
|
||
let empty = null;
|
||
console.log(empty); // null
|
||
|
||
// boolean
|
||
let isTrue = true;
|
||
let isFalse = false;
|
||
|
||
// number
|
||
let integer = 10;
|
||
let float = 3.14;
|
||
|
||
// string
|
||
let message = 'Hello, World!';
|
||
|
||
// symbol
|
||
let sym = Symbol('unique');
|
||
|
||
// bigint
|
||
let bigNumber = 1234567890123456789012345678901234567890n;
|
||
|
||
// object
|
||
let person = { name: 'John', age: 30 };
|
||
```
|
||
|
||
### 1.1.3 运算符
|
||
#### 算术运算符
|
||
```javascript
|
||
let a = 10;
|
||
let b = 5;
|
||
|
||
console.log(a + b); // 加法
|
||
console.log(a - b); // 减法
|
||
console.log(a * b); // 乘法
|
||
console.log(a / b); // 除法
|
||
console.log(a % b); // 取余
|
||
console.log(a ** b); // 幂运算
|
||
```
|
||
|
||
#### 比较运算符
|
||
```javascript
|
||
let x = 10;
|
||
let y = 20;
|
||
|
||
console.log(x == y); // 相等
|
||
console.log(x === y); // 严格相等
|
||
console.log(x != y); // 不相等
|
||
console.log(x !== y); // 严格不相等
|
||
console.log(x < y); // 小于
|
||
console.log(x > y); // 大于
|
||
console.log(x <= y); // 小于等于
|
||
console.log(x >= y); // 大于等于
|
||
```
|
||
|
||
#### 逻辑运算符
|
||
```javascript
|
||
let p = true;
|
||
let q = false;
|
||
|
||
console.log(p && q); // 逻辑与
|
||
console.log(p || q); // 逻辑或
|
||
console.log(!p); // 逻辑非
|
||
```
|
||
|
||
## 1.2 函数
|
||
|
||
### 1.2.1 函数声明
|
||
```javascript
|
||
function add(a, b) {
|
||
return a + b;
|
||
}
|
||
|
||
let result = add(3, 5);
|
||
console.log(result); // 8
|
||
```
|
||
|
||
### 1.2.2 箭头函数
|
||
```javascript
|
||
const multiply = (a, b) => a * b;
|
||
|
||
let product = multiply(4, 6);
|
||
console.log(product); // 24
|
||
```
|
||
|
||
### 1.2.3 函数作用域
|
||
```javascript
|
||
function outerFunction() {
|
||
let outerVar = 'I am outside';
|
||
|
||
function innerFunction() {
|
||
let innerVar = 'I am inside';
|
||
console.log(outerVar); // 可以访问外部变量
|
||
}
|
||
|
||
innerFunction();
|
||
// console.log(innerVar); // 报错,无法访问内部变量
|
||
}
|
||
|
||
outerFunction();
|
||
```
|
||
|
||
## 1.3 异步编程
|
||
|
||
### 1.3.1 Promise
|
||
Promise 是异步编程的一种解决方案,用于表示一个异步操作的最终完成(或失败)及其结果值。它有三种状态:`pending`(进行中)、`fulfilled`(已成功)和 `rejected`(已失败)。状态一旦改变,就不会再变。
|
||
```javascript
|
||
function fetchData() {
|
||
return new Promise((resolve, reject) => {
|
||
setTimeout(() => {
|
||
const success = true;
|
||
if (success) {
|
||
resolve('Data fetched successfully');
|
||
} else {
|
||
reject(new Error('Failed to fetch data'));
|
||
}
|
||
}, 2000);
|
||
});
|
||
}
|
||
|
||
fetchData()
|
||
.then(data => {
|
||
console.log(data);
|
||
})
|
||
.catch(error => {
|
||
console.error(error);
|
||
});
|
||
```
|
||
使用场景:处理异步操作,如网络请求、文件读取等,避免回调地狱。
|
||
|
||
### 1.3.2 Async/Await
|
||
`async/await` 是基于 Promise 的语法糖,它让异步代码看起来更像同步代码,提高了代码的可读性。`async` 函数总是返回一个 Promise,`await` 只能在 `async` 函数内部使用,用于等待一个 Promise 完成并返回其结果。
|
||
```javascript
|
||
async function getData() {
|
||
try {
|
||
let data = await fetchData();
|
||
console.log(data);
|
||
} catch (error) {
|
||
console.error(error);
|
||
}
|
||
}
|
||
|
||
getData();
|
||
```
|
||
使用场景:在需要按顺序执行多个异步操作时,使用 `async/await` 可以让代码更简洁易读。
|
||
|
||
### 1.3.3 事件循环
|
||
JavaScript 是单线程的,通过事件循环机制实现异步操作。事件循环主要包括调用栈、任务队列和微任务队列。调用栈用于执行同步代码,任务队列存放异步操作完成后的回调函数,微任务队列存放 Promise 的回调函数。事件循环会不断检查调用栈是否为空,若为空则从任务队列和微任务队列中取出任务执行。
|
||
```javascript
|
||
console.log('Start');
|
||
|
||
setTimeout(() => {
|
||
console.log('Timeout');
|
||
}, 0);
|
||
|
||
Promise.resolve().then(() => {
|
||
console.log('Promise');
|
||
});
|
||
|
||
console.log('End');
|
||
|
||
// 输出顺序:Start -> End -> Promise -> Timeout
|
||
```
|
||
使用场景:处理异步操作,保证代码的执行顺序符合预期。
|
||
|
||
## 1.4 ES6+ 特性
|
||
|
||
### 1.4.1 解构赋值
|
||
```javascript
|
||
// 数组解构
|
||
let [first, second] = [1, 2];
|
||
console.log(first); // 1
|
||
console.log(second); // 2
|
||
|
||
// 对象解构
|
||
let { name, age } = { name: 'John', age: 30 };
|
||
console.log(name); // John
|
||
console.log(age); // 30
|
||
```
|
||
|
||
### 1.4.2 扩展运算符
|
||
```javascript
|
||
// 数组扩展
|
||
let arr1 = [1, 2, 3];
|
||
let arr2 = [4, 5, 6];
|
||
let combined = [...arr1, ...arr2];
|
||
console.log(combined); // [1, 2, 3, 4, 5, 6]
|
||
|
||
// 对象扩展
|
||
let obj1 = { a: 1 };
|
||
let obj2 = { b: 2 };
|
||
let merged = { ...obj1, ...obj2 };
|
||
console.log(merged); // { a: 1, b: 2 }
|
||
```
|
||
|
||
### 1.4.3 类
|
||
```javascript
|
||
class Person {
|
||
constructor(name, age) {
|
||
this.name = name;
|
||
this.age = age;
|
||
}
|
||
|
||
greet() {
|
||
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
|
||
}
|
||
}
|
||
|
||
let person = new Person('John', 30);
|
||
person.greet(); // Hello, my name is John and I am 30 years old.
|
||
```
|
||
|
||
### 1.4.4 模块化
|
||
#### 导出模块
|
||
```javascript
|
||
// math.js
|
||
export function add(a, b) {
|
||
return a + b;
|
||
}
|
||
|
||
export const PI = 3.14;
|
||
```
|
||
|
||
#### 导入模块
|
||
```javascript
|
||
// main.js
|
||
import { add, PI } from './math.js';
|
||
|
||
console.log(add(3, 5)); // 8
|
||
console.log(PI); // 3.14
|
||
```
|
||
|
||
### 1.4.5 模板字符串
|
||
```javascript
|
||
let name = 'John';
|
||
let age = 30;
|
||
let message = `Hello, my name is ${name} and I am ${age} years old.`;
|
||
console.log(message);
|
||
```
|
||
|
||
### 1.4.6 默认参数
|
||
```javascript
|
||
function greet(name = 'Guest') {
|
||
console.log(`Hello, ${name}!`);
|
||
}
|
||
|
||
greet(); // Hello, Guest!
|
||
greet('John'); // Hello, John!
|
||
```
|
||
|
||
### 1.4.7 Rest 参数
|
||
```javascript
|
||
function sum(...numbers) {
|
||
return numbers.reduce((total, num) => total + num, 0);
|
||
}
|
||
|
||
console.log(sum(1, 2, 3)); // 6
|
||
console.log(sum(1, 2, 3, 4, 5)); // 15
|
||
```
|
||
|
||
### 1.4.8 Spread 参数
|
||
```javascript
|
||
let arr1 = [1, 2, 3];
|
||
let arr2 = [4, 5, 6];
|
||
let combined = [...arr1, ...arr2];
|
||
console.log(combined); // [1, 2, 3, 4, 5, 6]
|
||
|
||
let obj1 = { a: 1 };
|
||
let obj2 = { b: 2 };
|
||
let merged = { ...obj1, ...obj2 };
|
||
console.log(merged); // { a: 1, b: 2 }
|
||
```
|
||
|
||
### 1.4.9 Proxy
|
||
```javascript
|
||
let target = { name: 'John', age: 30 };
|
||
let handler = {
|
||
get: function(target, prop) {
|
||
console.log(`Getting property ${prop}`);
|
||
return target[prop];
|
||
},
|
||
set: function(target, prop, value) {
|
||
console.log(`Setting property ${prop} to ${value}`);
|
||
target[prop] = value;
|
||
return true;
|
||
}
|
||
};
|
||
|
||
let proxy = new Proxy(target, handler);
|
||
console.log(proxy.name); // Getting property name
|
||
// John
|
||
proxy.age = 31; // Setting property age to 31
|
||
```
|
||
|
||
### 1.4.10 Reflect
|
||
```javascript
|
||
let target = { name: 'John', age: 30 };
|
||
|
||
console.log(Reflect.get(target, 'name')); // John
|
||
Reflect.set(target, 'age', 31);
|
||
console.log(target.age); // 31
|
||
```
|
||
|
||
## 1.5 闭包
|
||
```javascript
|
||
function outer() {
|
||
let outerVar = 'I am outside';
|
||
|
||
function inner() {
|
||
console.log(outerVar);
|
||
}
|
||
|
||
return inner;
|
||
}
|
||
|
||
let closure = outer();
|
||
closure(); // I am outside
|
||
```
|
||
|
||
## 1.6 原型与继承
|
||
### 1.6.1 原型链
|
||
```javascript
|
||
function Animal(name) {
|
||
this.name = name;
|
||
}
|
||
|
||
Animal.prototype.speak = function() {
|
||
console.log(`${this.name} makes a noise.`);
|
||
};
|
||
|
||
let dog = new Animal('Dog');
|
||
// 先在 dog 对象本身查找 speak 方法,找不到则去 Animal.prototype 中查找
|
||
dog.speak(); // Dog makes a noise.
|
||
```
|
||
|
||
### 1.6.2 继承
|
||
```javascript
|
||
function Dog(name) {
|
||
// 构造函数继承,继承父类的属性
|
||
Animal.call(this, name);
|
||
}
|
||
|
||
// 原型链继承,继承父类的方法
|
||
Dog.prototype = Object.create(Animal.prototype);
|
||
Dog.prototype.constructor = Dog;
|
||
|
||
Dog.prototype.bark = function() {
|
||
console.log(`${this.name} barks.`);
|
||
};
|
||
|
||
let myDog = new Dog('Buddy');
|
||
myDog.speak(); // Buddy makes a noise.
|
||
myDog.bark(); // Buddy barks.
|
||
```
|
||
|
||
## 1.7 浏览器 API
|
||
### 1.7.1 DOM 操作
|
||
```javascript
|
||
// 获取元素
|
||
let element = document.getElementById('myElement');
|
||
|
||
// 创建元素
|
||
let newElement = document.createElement('p');
|
||
newElement.textContent = 'This is a new paragraph.';
|
||
|
||
// 添加元素
|
||
let parent = document.body;
|
||
parent.appendChild(newElement);
|
||
|
||
// 修改元素样式
|
||
newElement.style.color = 'red';
|
||
```
|
||
|
||
### 1.7.2 事件处理
|
||
```javascript
|
||
let button = document.getElementById('myButton');
|
||
button.addEventListener('click', function() {
|
||
alert('Button clicked!');
|
||
});
|
||
```
|
||
|
||
### 1.7.3 本地存储
|
||
```javascript
|
||
// 设置本地存储
|
||
localStorage.setItem('name', 'John');
|
||
|
||
// 获取本地存储
|
||
let name = localStorage.getItem('name');
|
||
console.log(name); // John
|
||
|
||
// 删除本地存储
|
||
localStorage.removeItem('name');
|
||
```
|
||
|
||
### 1.7.4 定时器
|
||
```javascript
|
||
// setTimeout
|
||
setTimeout(function() {
|
||
console.log('This will be executed after 2 seconds');
|
||
}, 2000);
|
||
|
||
// setInterval
|
||
let intervalId = setInterval(function() {
|
||
console.log('This will be executed every 1 second');
|
||
}, 1000);
|
||
|
||
// 清除定时器
|
||
clearInterval(intervalId);
|
||
```
|
||
|
||
## 1.8 Node.js
|
||
### 1.8.1 文件系统操作
|
||
```javascript
|
||
const fs = require('fs');
|
||
|
||
// 读取文件
|
||
fs.readFile('example.txt', 'utf8', function(err, data) {
|
||
if (err) throw err;
|
||
console.log(data);
|
||
});
|
||
|
||
// 写入文件
|
||
fs.writeFile('example.txt', 'Hello, Node.js!', function(err) {
|
||
if (err) throw err;
|
||
console.log('File written successfully');
|
||
});
|
||
```
|
||
|
||
### 1.8.2 模块系统
|
||
```javascript
|
||
// module.js
|
||
const add = (a, b) => a + b;
|
||
|
||
module.exports = {
|
||
add
|
||
};
|
||
|
||
// main.js
|
||
const myModule = require('./module');
|
||
|
||
console.log(myModule.add(3, 5)); // 8
|
||
```
|
||
|
||
### 1.8.3 HTTP 服务器
|
||
```javascript
|
||
const http = require('http');
|
||
|
||
const server = http.createServer((req, res) => {
|
||
res.statusCode = 200;
|
||
res.setHeader('Content-Type', 'text/plain');
|
||
res.end('Hello, World!');
|
||
});
|
||
|
||
server.listen(3000, '127.0.0.1', () => {
|
||
console.log('Server running at http://127.0.0.1:3000/');
|
||
});
|
||
```
|
||
|
||
## 1.9 正则表达式
|
||
### 1.9.1 基本语法
|
||
```javascript
|
||
let pattern = /abc/;
|
||
let str = 'abcdef';
|
||
|
||
console.log(pattern.test(str)); // true
|
||
```
|
||
|
||
### 1.9.2 元字符
|
||
```javascript
|
||
// 匹配任意字符
|
||
let pattern = /a.c/;
|
||
let str = 'abc';
|
||
console.log(pattern.test(str)); // true
|
||
|
||
// 匹配开始位置
|
||
let pattern = /^a/;
|
||
let str = 'abc';
|
||
console.log(pattern.test(str)); // true
|
||
|
||
// 匹配结束位置
|
||
let pattern = /c$/;
|
||
let str = 'abc';
|
||
console.log(pattern.test(str)); // true
|
||
```
|
||
|
||
### 1.9.3 量词
|
||
```javascript
|
||
// 匹配零个或多个
|
||
let pattern = /a*/;
|
||
let str = 'aaaa';
|
||
console.log(pattern.test(str)); // true
|
||
|
||
// 匹配一个或多个
|
||
let pattern = /a+/;
|
||
let str = 'aaaa';
|
||
console.log(pattern.test(str)); // true
|
||
|
||
// 匹配零个或一个
|
||
let pattern = /a?/;
|
||
let str = 'a';
|
||
console.log(pattern.test(str)); // true
|
||
```
|
||
|
||
## 1.10 错误处理
|
||
### 1.10.1 try...catch
|
||
```javascript
|
||
try {
|
||
let result = 1 / 0;
|
||
if (result === Infinity) {
|
||
throw new Error('Division by zero');
|
||
}
|
||
} catch (error) {
|
||
console.error(error.message); // Division by zero
|
||
} finally {
|
||
console.log('This will always be executed');
|
||
}
|
||
```
|
||
|
||
### 1.10.2 自定义错误
|
||
```javascript
|
||
class CustomError extends Error {
|
||
constructor(message) {
|
||
super(message);
|
||
this.name = 'CustomError';
|
||
}
|
||
}
|
||
|
||
try {
|
||
throw new CustomError('This is a custom error');
|
||
} catch (error) {
|
||
console.error(error.name + ': ' + error.message); // CustomError: This is a custom error
|
||
}
|
||
|
||
## 1.11 Web API 扩展
|
||
### 1.11.1 Fetch API
|
||
Fetch API 提供了一个 JavaScript 接口,用于访问和操纵 HTTP 管道的部分,例如请求和响应。它还提供了一个全局 `fetch()` 方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源。
|
||
```javascript
|
||
// 基本用法
|
||
fetch('https://api.example.com/data')
|
||
.then(response => {
|
||
if (!response.ok) {
|
||
throw new Error('Network response was not ok');
|
||
}
|
||
return response.json();
|
||
})
|
||
.then(data => {
|
||
console.log(data);
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
});
|
||
|
||
// 带请求体的 POST 请求
|
||
const postData = {
|
||
name: 'John Doe',
|
||
age: 30
|
||
};
|
||
|
||
fetch('https://api.example.com/submit', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
},
|
||
body: JSON.stringify(postData)
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
console.log(data);
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
});
|
||
```
|
||
|
||
### 1.11.2 Web Workers
|
||
Web Workers 使得一个 Web 应用程序可以在与主执行线程分离的后台线程中运行一个脚本操作。这样做的好处是可以在一个单独的线程中执行费时的处理任务,从而允许主(通常是 UI)线程继续运行而不被阻塞。
|
||
```javascript
|
||
// main.js
|
||
if (typeof Worker !== 'undefined') {
|
||
// 创建一个新的 worker
|
||
const worker = new Worker('worker.js');
|
||
|
||
// 向 worker 发送消息
|
||
worker.postMessage('Hello from main script');
|
||
|
||
// 接收 worker 的消息
|
||
worker.onmessage = function(e) {
|
||
console.log('Received message from worker:', e.data);
|
||
// 终止 worker
|
||
worker.terminate();
|
||
};
|
||
|
||
worker.onerror = function(error) {
|
||
console.error('Worker error:', error.message);
|
||
};
|
||
} else {
|
||
console.error('Web Workers are not supported in this environment.');
|
||
}
|
||
|
||
// worker.js
|
||
self.onmessage = function(e) {
|
||
console.log('Received message from main script:', e.data);
|
||
// 向主脚本发送消息
|
||
self.postMessage('Hello from worker');
|
||
};
|
||
```
|
||
|
||
### 1.11.3 WebSocket
|
||
WebSocket 是一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。
|
||
```javascript
|
||
// 客户端代码
|
||
const socket = new WebSocket('ws://echo.websocket.org');
|
||
|
||
// 连接建立时触发
|
||
socket.addEventListener('open', function (event) {
|
||
socket.send('Hello, WebSocket!');
|
||
});
|
||
|
||
// 接收到消息时触发
|
||
socket.addEventListener('message', function (event) {
|
||
console.log('Received message:', event.data);
|
||
});
|
||
|
||
// 连接关闭时触发
|
||
socket.addEventListener('close', function (event) {
|
||
if (event.wasClean) {
|
||
console.log('Connection closed cleanly');
|
||
} else {
|
||
console.log('Connection died');
|
||
}
|
||
});
|
||
|
||
// 发生错误时触发
|
||
socket.addEventListener('error', function (event) {
|
||
console.error('WebSocket error:', event);
|
||
});
|
||
```
|
||
|
||
## 1.12 性能优化
|
||
### 1.12.1 代码压缩与混淆
|
||
代码压缩和混淆是提高网站性能的重要手段。压缩可以减少代码的体积,从而减少网络传输时间;混淆可以使代码更难被逆向工程,同时也能进一步减小代码体积。
|
||
```javascript
|
||
// 示例:使用 UglifyJS 压缩代码
|
||
const UglifyJS = require('uglify-js');
|
||
const code = 'function add(a, b) { return a + b; }';
|
||
const result = UglifyJS.minify(code);
|
||
|
||
if (result.error) {
|
||
console.error('Error:', result.error);
|
||
} else {
|
||
console.log('Minified code:', result.code);
|
||
}
|
||
```
|
||
|
||
### 1.12.2 懒加载
|
||
懒加载是一种优化技术,它允许你在需要时才加载资源,而不是在页面加载时就全部加载。这可以显著减少初始加载时间,提高用户体验。
|
||
```html
|
||
<!-- 图片懒加载示例 -->
|
||
<img loading="lazy" src="image.jpg" alt="Lazy loaded image">
|
||
|
||
<!-- JavaScript 模块懒加载示例 -->
|
||
<button id="loadModule">Load Module</button>
|
||
<script>
|
||
const loadModuleButton = document.getElementById('loadModule');
|
||
loadModuleButton.addEventListener('click', async () => {
|
||
const { default: myModule } = await import('./myModule.js');
|
||
myModule.doSomething();
|
||
});
|
||
</script>
|
||
```
|
||
|
||
### 1.12.3 事件委托
|
||
事件委托是一种利用事件冒泡机制来处理事件的技术。通过将事件监听器添加到父元素上,可以减少事件监听器的数量,从而提高性能。
|
||
```html
|
||
<ul id="myList">
|
||
<li>Item 1</li>
|
||
<li>Item 2</li>
|
||
<li>Item 3</li>
|
||
</ul>
|
||
|
||
<script>
|
||
const myList = document.getElementById('myList');
|
||
myList.addEventListener('click', function(event) {
|
||
if (event.target.tagName === 'LI') {
|
||
console.log('Clicked on:', event.target.textContent);
|
||
}
|
||
});
|
||
</script>
|
||
```
|
||
|
||
## 1.13 设计模式
|
||
### 1.13.1 单例模式
|
||
单例模式确保一个类只有一个实例,并提供一个全局访问点。
|
||
```javascript
|
||
class Singleton {
|
||
constructor() {
|
||
if (!Singleton.instance) {
|
||
this.data = [];
|
||
Singleton.instance = this;
|
||
}
|
||
return Singleton.instance;
|
||
}
|
||
|
||
addItem(item) {
|
||
this.data.push(item);
|
||
}
|
||
|
||
getItems() {
|
||
return this.data;
|
||
}
|
||
}
|
||
|
||
const singleton1 = new Singleton();
|
||
const singleton2 = new Singleton();
|
||
|
||
singleton1.addItem('Item 1');
|
||
console.log(singleton2.getItems()); // ['Item 1']
|
||
```
|
||
|
||
### 1.13.2 观察者模式
|
||
观察者模式定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。
|
||
```javascript
|
||
class Subject {
|
||
constructor() {
|
||
this.observers = [];
|
||
}
|
||
|
||
subscribe(observer) {
|
||
this.observers.push(observer);
|
||
}
|
||
|
||
unsubscribe(observer) {
|
||
this.observers = this.observers.filter(obs => obs !== observer);
|
||
}
|
||
|
||
notify(data) {
|
||
this.observers.forEach(observer => observer.update(data));
|
||
}
|
||
}
|
||
|
||
class Observer {
|
||
constructor(name) {
|
||
this.name = name;
|
||
}
|
||
|
||
update(data) {
|
||
console.log(`${this.name} received data: ${data}`);
|
||
}
|
||
}
|
||
|
||
const subject = new Subject();
|
||
const observer1 = new Observer('Observer 1');
|
||
const observer2 = new Observer('Observer 2');
|
||
|
||
subject.subscribe(observer1);
|
||
subject.subscribe(observer2);
|
||
subject.notify('Hello, observers!');
|
||
```
|
||
|
||
### 1.13.3 工厂模式
|
||
工厂模式是一种创建对象的设计模式,它将对象的创建和使用分离,通过一个工厂函数来创建对象。
|
||
```javascript
|
||
class Product {
|
||
constructor(name) {
|
||
this.name = name;
|
||
}
|
||
|
||
showInfo() {
|
||
console.log(`This is a ${this.name}`);
|
||
}
|
||
}
|
||
|
||
function productFactory(name) {
|
||
return new Product(name);
|
||
}
|
||
|
||
const product1 = productFactory('Laptop');
|
||
const product2 = productFactory('Smartphone');
|
||
|
||
product1.showInfo(); // This is a Laptop
|
||
product2.showInfo(); // This is a Smartphone
|
||
```
|
||
|
||
## 1.14 测试与调试
|
||
### 1.14.1 单元测试
|
||
单元测试是对软件中的最小可测试单元进行检查和验证。在 JavaScript 中,常用的单元测试框架有 Jest、Mocha 等。
|
||
```javascript
|
||
// math.js
|
||
function add(a, b) {
|
||
return a + b;
|
||
}
|
||
|
||
module.exports = add;
|
||
|
||
// math.test.js
|
||
const add = require('./math');
|
||
const { test, expect } = require('@jest/globals');
|
||
|
||
test('adds 1 + 2 to equal 3', () => {
|
||
expect(add(1, 2)).toBe(3);
|
||
});
|
||
```
|
||
|
||
### 1.14.2 调试技巧
|
||
在 JavaScript 中,可以使用浏览器的开发者工具进行调试。常用的调试技巧包括设置断点、使用 `console.log()` 输出调试信息等。
|
||
```javascript
|
||
function calculateSum(arr) {
|
||
let sum = 0;
|
||
for (let i = 0; i < arr.length; i++) {
|
||
console.log(`Current element: ${arr[i]}`);
|
||
sum += arr[i];
|
||
}
|
||
return sum;
|
||
}
|
||
|
||
const numbers = [1, 2, 3, 4, 5];
|
||
const result = calculateSum(numbers);
|
||
console.log(`Sum: ${result}`);
|
||
```
|
||
|
||
## 1.15 安全相关
|
||
### 1.15.1 XSS 防护
|
||
跨站脚本攻击(XSS)是一种常见的 Web 安全漏洞,攻击者通过注入恶意脚本到网页中,从而窃取用户信息。可以通过对用户输入进行过滤和转义来防止 XSS 攻击。
|
||
```javascript
|
||
function escapeHtml(unsafe) {
|
||
return unsafe
|
||
.replace(/&/g, "&")
|
||
.replace(/</g, "<")
|
||
.replace(/>/g, ">")
|
||
.replace(/"/g, """)
|
||
.replace(/'/g, "'");
|
||
}
|
||
|
||
const userInput = '<script>alert("XSS")</script>';
|
||
const safeInput = escapeHtml(userInput);
|
||
console.log(safeInput); // <script>alert("XSS")</script>
|
||
```
|
||
|
||
### 1.15.2 CSRF 防护
|
||
跨站请求伪造(CSRF)是一种通过伪造用户请求来执行恶意操作的攻击。可以通过使用 CSRF Token 来防止 CSRF 攻击。
|
||
```javascript
|
||
// 服务器端生成 CSRF Token
|
||
const csrfToken = 'abc123';
|
||
|
||
// 客户端发送请求时携带 CSRF Token
|
||
fetch('https://api.example.com/submit', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRF-Token': csrfToken
|
||
},
|
||
body: JSON.stringify({ data: 'example' })
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
console.log(data);
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
});
|
||
```
|
||
|
||
## 1.16 国际化与本地化
|
||
### 1.16.1 Intl 对象
|
||
Intl 对象是 ECMAScript 国际化 API 的命名空间,它提供了格式化数字、日期和时间以及比较字符串的功能。
|
||
```javascript
|
||
// 格式化日期
|
||
const date = new Date();
|
||
const options = { year: 'numeric', month: 'long', day: 'numeric' };
|
||
const formatter = new Intl.DateTimeFormat('zh-CN', options);
|
||
console.log(formatter.format(date));
|
||
|
||
// 格式化数字
|
||
const number = 1234567.89;
|
||
const numberFormatter = new Intl.NumberFormat('zh-CN', {
|
||
style: 'currency',
|
||
currency: 'CNY'
|
||
});
|
||
console.log(numberFormatter.format(number)); // ¥1,234,567.89
|
||
```
|
||
|
||
### 1.16.2 多语言支持
|
||
在 JavaScript 中,可以通过动态加载不同语言的资源文件来实现多语言支持。
|
||
```javascript
|
||
// 语言资源文件 en.js
|
||
const en = {
|
||
greeting: 'Hello!',
|
||
welcome: 'Welcome to our website.'
|
||
};
|
||
|
||
// 语言资源文件 zh.js
|
||
const zh = {
|
||
greeting: '你好!',
|
||
welcome: '欢迎来到我们的网站。'
|
||
};
|
||
|
||
// 动态加载语言资源
|
||
function loadLanguage(lang) {
|
||
if (lang === 'en') {
|
||
return en;
|
||
} else if (lang === 'zh') {
|
||
return zh;
|
||
}
|
||
}
|
||
|
||
const currentLang = 'zh';
|
||
const langResources = loadLanguage(currentLang);
|
||
console.log(langResources.greeting); // 你好!
|
||
```
|
||
|
||
## 1.17 服务端渲染(SSR)与静态站点生成(SSG)
|
||
### 1.17.1 服务端渲染
|
||
服务端渲染是指在服务器端将组件或页面渲染成 HTML 字符串,然后发送给客户端。这样可以提高首屏加载速度,有利于 SEO。
|
||
```javascript
|
||
// 使用 Node.js 和 Express 进行简单的服务端渲染
|
||
const express = require('express');
|
||
const app = express();
|
||
|
||
app.get('/', (req, res) => {
|
||
const html = `<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<title>Server-Side Rendering</title>
|
||
</head>
|
||
<body>
|
||
<h1>Hello, Server-Side Rendering!</h1>
|
||
</body>
|
||
</html>`;
|
||
res.send(html);
|
||
});
|
||
|
||
const port = 3000;
|
||
app.listen(port, () => {
|
||
console.log(`Server running at http://localhost:${port}`);
|
||
});
|
||
```
|
||
|
||
### 1.17.2 静态站点生成
|
||
静态站点生成是指在构建时将组件或页面渲染成静态 HTML 文件,然后部署到服务器。这样可以提供更快的加载速度和更好的性能。
|
||
```javascript
|
||
// 使用 Next.js 进行静态站点生成
|
||
// pages/index.js
|
||
import React from 'react';
|
||
|
||
const HomePage = () => {
|
||
return (
|
||
<div>
|
||
<h1>Hello, Static Site Generation!</h1>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export async function getStaticProps() {
|
||
// 可以在这里获取数据
|
||
return {
|
||
props: {},
|
||
revalidate: 60 * 60 // 每小时重新生成一次
|
||
};
|
||
};
|
||
|
||
export default HomePage;
|
||
```
|
||
|
||
## 1.18 代码规范与最佳实践
|
||
### 1.18.1 ESLint 配置
|
||
ESLint 是一个用于识别和报告 JavaScript 代码中模式问题的工具。可以通过配置 ESLint 来强制执行代码规范。
|
||
```json
|
||
// .eslintrc.json
|
||
{
|
||
"extends": "eslint:recommended",
|
||
"rules": {
|
||
"semi": ["error", "always"],
|
||
"quotes": ["error", "single"]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 1.18.2 模块化开发
|
||
模块化开发可以提高代码的可维护性和可复用性。在 JavaScript 中,可以使用 ES6 模块或 CommonJS 模块。
|
||
```javascript
|
||
// 示例:ES6 模块
|
||
// utils.js
|
||
export function add(a, b) {
|
||
return a + b;
|
||
}
|
||
|
||
// main.js
|
||
import { add } from './utils.js';
|
||
|
||
const result = add(3, 5);
|
||
console.log(result); // 8
|
||
```
|
||
|
||
### 1.18.3 避免全局变量
|
||
全局变量可能会导致命名冲突和代码难以维护。应该尽量避免使用全局变量,而是使用模块作用域或函数作用域。
|
||
```javascript
|
||
// 不好的做法
|
||
var globalVar = 'This is a global variable';
|
||
|
||
// 好的做法
|
||
function myModule() {
|
||
const localVar = 'This is a local variable';
|
||
return localVar;
|
||
}
|
||
|
||
const result = myModule();
|
||
console.log(result); // This is a local variable
|
||
```
|
||
|
||
## 1.19 构建工具
|
||
### 1.19.1 Webpack
|
||
Webpack 是一个现代 JavaScript 应用程序的静态模块打包器。它可以将多个模块打包成一个或多个文件。
|
||
```javascript
|
||
// webpack.config.js
|
||
const path = require('path');
|
||
|
||
module.exports = {
|
||
entry: './src/index.js',
|
||
output: {
|
||
path: path.resolve(__dirname, 'dist'),
|
||
filename: 'bundle.js'
|
||
},
|
||
module: {
|
||
rules: [
|
||
{ test: /\.js$/, exclude: /node_modules/, use: 'babel-loader' }
|
||
]
|
||
}
|
||
};
|
||
```
|
||
|
||
### 1.19.2 Vite
|
||
Vite 是一个面向现代浏览器的前端构建工具,它具有快速的冷启动和热更新能力。
|
||
```bash
|
||
# 创建 Vite 项目
|
||
npm init vite@latest my-project -- --template react
|
||
cd my-project
|
||
npm install
|
||
npm run dev
|
||
```
|
||
|
||
## 1.20 前沿技术与趋势
|
||
### 1.20.1 WebAssembly
|
||
WebAssembly 是一种新的编码方式,可以在现代的网络浏览器中运行 - 它是一种低级的类汇编语言,具有紧凑的二进制格式,可以接近原生性能运行,并为诸如 C、C++ 等语言提供一个编译目标,以便它们可以在 Web 上运行。
|
||
```javascript
|
||
// 加载 WebAssembly 模块
|
||
async function loadWasm() {
|
||
const response = await fetch('example.wasm');
|
||
const buffer = await response.arrayBuffer();
|
||
const module = await WebAssembly.compile(buffer);
|
||
const instance = await WebAssembly.instantiate(module);
|
||
const result = instance.exports.add(3, 5);
|
||
console.log(result); // 8
|
||
}
|
||
|
||
loadWasm();
|
||
```
|
||
|
||
### 1.20.2 渐进式 Web 应用(PWA)
|
||
渐进式 Web 应用是一种可以提供类似原生应用体验的 Web 应用。它具有离线访问、推送通知等功能。
|
||
```javascript
|
||
// service-worker.js
|
||
self.addEventListener('install', function(event) {
|
||
event.waitUntil(
|
||
caches.open('my-cache').then(function(cache) {
|
||
return cache.addAll([
|
||
'/',
|
||
'/index.html',
|
||
'/styles.css',
|
||
'/script.js'
|
||
]);
|
||
})
|
||
);
|
||
});
|
||
|
||
self.addEventListener('fetch', function(event) {
|
||
event.respondWith(
|
||
caches.match(event.request).then(function(response) {
|
||
return response || fetch(event.request);
|
||
})
|
||
);
|
||
});
|
||
```
|
||
|
||
This concludes the comprehensive guide to JavaScript, covering everything from basic syntax to advanced features and modern web development trends.`}}} |