现代 JavaScript 开发指南
简介
JavaScript 是 Web 开发的核心语言,也是当今最流行的编程语言之一。从最初的简单脚本语言,到如今的全栈开发语言,JavaScript 已经发展成为一个功能强大、生态丰富的编程语言。本文将全面介绍现代 JavaScript 的核心概念、新特性和最佳实践,帮助开发者掌握这门语言的精髓。
基础概念
1. 变量声明
javascript
// 使用 let 和 const
let count = 0; // 可变变量
const MAX_COUNT = 100; // 不可变常量
// 解构赋值
const [first, second] = [1, 2]; // 数组解构
const { name, age } = { name: 'John', age: 30 }; // 对象解构
const { name: userName, age: userAge } = { name: 'John', age: 30 }; // 重命名
// 剩余参数解构
const [firstItem, ...restItems] = [1, 2, 3, 4, 5];
const { firstName, ...otherInfo } = { firstName: 'John', lastName: 'Doe', age: 30 };2. 函数
javascript
// 箭头函数
const add = (a, b) => a + b;
const multiply = (a, b) => {
return a * b;
};
// 默认参数
function greet(name = 'Guest') {
return `Hello, ${name}!`;
}
// 剩余参数
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
// 展开运算符
const numbers = [1, 2, 3];
const max = Math.max(...numbers);
// 箭头函数与 this
const person = {
name: 'John',
sayHello: function() {
setTimeout(() => {
console.log(`Hello, my name is ${this.name}`); // this 指向 person 对象
}, 1000);
}
};3. 模板字符串
javascript
// 基本用法
const name = 'John';
const greeting = `Hello, ${name}!`;
// 多行字符串
const multiLine = `
This is a
multi-line
string
`;
// 表达式
const a = 10;
const b = 20;
const result = `${a} + ${b} = ${a + b}`;
// 标签模板
function highlight(strings, ...values) {
return strings.reduce((result, string, index) => {
return result + string + (values[index] ? `<mark>${values[index]}</mark>` : '');
}, '');
}
const price = 20;
const message = highlight`The price is ${price} dollars`;4. 数组和对象方法
javascript
// 数组方法
const numbers = [1, 2, 3, 4, 5];
// map: 转换数组
const doubled = numbers.map(n => n * 2);
// filter: 过滤数组
const evenNumbers = numbers.filter(n => n % 2 === 0);
// reduce: 归约数组
const sum = numbers.reduce((acc, curr) => acc + curr, 0);
// find: 查找元素
const found = numbers.find(n => n > 3);
// includes: 检查元素是否存在
const hasThree = numbers.includes(3);
// 对象方法
const person = {
name: 'John',
age: 30
};
// Object.keys: 获取对象键
const keys = Object.keys(person);
// Object.values: 获取对象值
const values = Object.values(person);
// Object.entries: 获取键值对
const entries = Object.entries(person);
// Object.assign: 合并对象
const updatedPerson = Object.assign({}, person, { age: 31 });
// 扩展运算符: 合并对象
const newPerson = { ...person, age: 31, city: 'New York' };现代特性
1. 异步编程
javascript
// Promise 基础
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const success = true;
if (success) {
resolve('Data fetched successfully!');
} else {
reject('Failed to fetch data');
}
}, 1000);
});
};
// Promise 链式调用
fetchData()
.then(data => {
console.log(data);
return 'Processed data';
})
.then(result => {
console.log(result);
})
.catch(error => {
console.error(error);
})
.finally(() => {
console.log('Operation completed');
});
// Promise.all: 并行执行多个 Promise
const promise1 = fetch('https://api.example.com/data1');
const promise2 = fetch('https://api.example.com/data2');
Promise.all([promise1, promise2])
.then(responses => Promise.all(responses.map(res => res.json())))
.then(data => {
console.log('All data:', data);
})
.catch(error => {
console.error('Error:', error);
});
// Async/Await
async function getData() {
try {
const result = await fetchData();
console.log(result);
// 连续 await
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error:', error);
} finally {
console.log('Cleanup');
}
}
// 异步函数返回 Promise
async function processData() {
const data = await fetchData();
return data.toUpperCase();
}
processData().then(result => console.log(result));2. 模块化
javascript
// ES 模块 - 导出
// helper.js
export const formatDate = (date) => date.toLocaleDateString();
export const validateEmail = (email) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
export default {
formatDate,
validateEmail
};
// ES 模块 - 导入
// main.js
import { formatDate, validateEmail } from './helper.js';
import helper from './helper.js';
// 动态导入
async function loadModule() {
const module = await import('./helper.js');
console.log(module.formatDate(new Date()));
}
// CommonJS 模块 (Node.js)
// helper.cjs
module.exports = {
formatDate: (date) => date.toLocaleDateString(),
validateEmail: (email) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
};
// main.cjs
const { formatDate } = require('./helper.cjs');3. 解构和扩展运算符
javascript
// 数组解构
const [a, b, ...rest] = [1, 2, 3, 4, 5];
// 对象解构
const { name, age, ...other } = { name: 'John', age: 30, city: 'New York', country: 'USA' };
// 函数参数解构
function printUser({ name, age }) {
console.log(`${name} is ${age} years old`);
}
const user = { name: 'John', age: 30 };
printUser(user);
// 扩展运算符
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2];
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const merged = { ...obj1, ...obj2 };
// 函数参数展开
function sum(a, b, c) {
return a + b + c;
}
const numbers = [1, 2, 3];
sum(...numbers);4. 集合类型
javascript
// Set: 无序唯一值集合
const set = new Set([1, 2, 3, 3, 4]);
set.add(5);
set.delete(1);
set.has(2); // true
set.size; // 4
// 遍历 Set
for (const item of set) {
console.log(item);
}
// Map: 键值对集合
const map = new Map();
map.set('name', 'John');
map.set('age', 30);
map.get('name'); // 'John'
map.has('age'); // true
map.delete('age');
map.size; // 1
// 遍历 Map
for (const [key, value] of map) {
console.log(`${key}: ${value}`);
}
// WeakSet 和 WeakMap
// 弱引用,不会阻止垃圾回收
const weakSet = new WeakSet();
const weakMap = new WeakMap();
// Symbol: 唯一标识符
const symbol1 = Symbol('description');
const symbol2 = Symbol('description');
console.log(symbol1 === symbol2); // false
// 使用 Symbol 作为对象属性
const obj = {
[symbol1]: 'value1',
[symbol2]: 'value2'
};
// BigInt: 大整数
const bigNumber = 1234567890123456789012345678901234567890n;
const anotherBigNumber = BigInt('1234567890123456789012345678901234567890');5. 现代操作符
javascript
// 可选链操作符 (?.)
const user = {
name: 'John',
address: {
street: '123 Main St'
}
};
// 安全访问嵌套属性
const street = user?.address?.street;
const zipCode = user?.address?.zipCode; // undefined,不会抛出错误
// 可选链调用函数
const user2 = {
name: 'Jane',
sayHello: function() {
return `Hello, ${this.name}!`;
}
};
const greeting = user2?.sayHello?.(); // "Hello, Jane!"
const greeting2 = user?.sayHello?.(); // undefined
// 空值合并操作符 (??)
const name = null ?? 'Default Name'; // "Default Name"
const age = 0 ?? 18; // 0 (0 不是 null 或 undefined)
const email = '' ?? 'default@example.com'; // "" (空字符串不是 null 或 undefined)
// 空值赋值操作符 (??=)
let username = null;
username ??= 'Guest'; // "Guest"
let existingUsername = 'John';
existingUsername ??= 'Guest'; // "John" (已有值,不会被覆盖)
// 逻辑或赋值操作符 (||=)
let count = 0;
count ||= 10; // 10 (0 是 falsy 值)
let existingCount = 5;
existingCount ||= 10; // 5 (已有真值,不会被覆盖)
// 逻辑与赋值操作符 (&&=)
let isValid = true;
isValid &&= false; // false
let existingValid = true;
existingValid &&= true; // true面向对象编程
1. 类
javascript
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hello, I'm ${this.name}`;
}
get fullName() {
return this.name;
}
set fullName(value) {
this.name = value;
}
static create(name, age) {
return new Person(name, age);
}
}
class Employee extends Person {
constructor(name, age, role, salary) {
super(name, age);
this.role = role;
this.salary = salary;
}
getDetails() {
return `${super.greet()}, I work as a ${this.role}`;
}
// 重写方法
greet() {
return `Hello from Employee: ${this.name}`;
}
}
// 使用类
const person = new Person('John', 30);
const employee = new Employee('Jane', 25, 'Developer', 80000);
const personFromStatic = Person.create('Bob', 35);2. 原型继承
javascript
// 构造函数
function Animal(name) {
this.name = name;
}
// 原型方法
Animal.prototype.speak = function() {
return `${this.name} makes a sound.`;
};
// 继承
function Dog(name, breed) {
Animal.call(this, name); // 调用父构造函数
this.breed = breed;
}
// 设置原型链
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
// 添加子类方法
Dog.prototype.bark = function() {
return `${this.name} barks!`;
};
// 重写父类方法
Dog.prototype.speak = function() {
return `${this.name} woofs!`;
};
// 使用
const dog = new Dog('Rex', 'German Shepherd');
dog.speak(); // "Rex woofs!"
dog.bark(); // "Rex barks!"3. 混入 (Mixins)
javascript
// 混入对象
const canEat = {
eat() {
console.log(`${this.name} is eating`);
}
};
const canSleep = {
sleep() {
console.log(`${this.name} is sleeping`);
}
};
// 应用混入
class Animal {
constructor(name) {
this.name = name;
}
}
// 合并混入
Object.assign(Animal.prototype, canEat, canSleep);
// 使用
const cat = new Animal('Whiskers');
cat.eat(); // "Whiskers is eating"
cat.sleep(); // "Whiskers is sleeping"函数式编程
1. 高阶函数
javascript
// 高阶函数:接受或返回函数的函数
function createMultiplier(factor) {
return function(number) {
return number * factor;
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
double(5); // 10
triple(5); // 15
// 数组高阶函数
const numbers = [1, 2, 3, 4, 5];
// map: 转换数组
const doubled = numbers.map(n => n * 2);
// filter: 过滤数组
const evenNumbers = numbers.filter(n => n % 2 === 0);
// reduce: 归约数组
const sum = numbers.reduce((acc, curr) => acc + curr, 0);
// find: 查找元素
const firstGreaterThanThree = numbers.find(n => n > 3);
// findIndex: 查找元素索引
const indexOfThree = numbers.findIndex(n => n === 3);
// every: 检查所有元素
const allPositive = numbers.every(n => n > 0);
// some: 检查至少一个元素
const hasEven = numbers.some(n => n % 2 === 0);
// forEach: 遍历数组
numbers.forEach(n => console.log(n));2. 纯函数
javascript
// 纯函数:相同输入总是产生相同输出,无副作用
function add(a, b) {
return a + b;
}
function calculateTotal(prices, taxRate) {
const subtotal = prices.reduce((sum, price) => sum + price, 0);
return subtotal * (1 + taxRate);
}
// 不纯函数:依赖外部状态或产生副作用
let total = 0;
function addToTotal(n) {
total += n; // 修改外部状态
console.log(`Total: ${total}`); // 产生副作用
return total;
}
// 不纯函数:修改参数
function updateUser(user, newData) {
user.name = newData.name; // 修改输入参数
return user;
}
// 纯函数版本:返回新对象
function updateUserPure(user, newData) {
return { ...user, ...newData };
}3. 柯里化
javascript
// 柯里化:将多参数函数转换为单参数函数序列
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return function(...moreArgs) {
return curried.apply(this, args.concat(moreArgs));
};
}
};
}
// 示例
function add(a, b, c) {
return a + b + c;
}
const curriedAdd = curry(add);
const add5 = curriedAdd(5);
const add5And10 = add5(10);
add5And10(15); // 30
// 箭头函数柯里化
const multiply = (a) => (b) => (c) => a * b * c;
const multiplyBy2 = multiply(2);
const multiplyBy2And3 = multiplyBy2(3);
multiplyBy2And3(4); // 244. 组合函数
javascript
// 组合:将多个函数组合成一个函数
function compose(...fns) {
return function(x) {
return fns.reduceRight((acc, fn) => fn(acc), x);
};
}
// 管道:从左到右组合函数
function pipe(...fns) {
return function(x) {
return fns.reduce((acc, fn) => fn(acc), x);
};
}
// 示例
const add1 = x => x + 1;
const multiply2 = x => x * 2;
const subtract3 = x => x - 3;
const composed = compose(subtract3, multiply2, add1);
composed(5); // (5 + 1) * 2 - 3 = 9
const piped = pipe(add1, multiply2, subtract3);
piped(5); // (5 + 1) * 2 - 3 = 9错误处理
1. Try-Catch
javascript
try {
// 可能抛出错误的代码
const result = riskyOperation();
console.log('Operation successful:', result);
} catch (error) {
console.error('Error occurred:', error.message);
// 可以根据错误类型进行不同处理
if (error instanceof TypeError) {
console.error('Type error:', error);
} else if (error instanceof RangeError) {
console.error('Range error:', error);
}
} finally {
// 总是执行的代码,用于清理资源
console.log('Cleanup operations');
}2. 自定义错误
javascript
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = 'ValidationError';
this.field = field;
}
}
class AuthenticationError extends Error {
constructor(message) {
super(message);
this.name = 'AuthenticationError';
}
}
function validateUser(user) {
if (!user.name) {
throw new ValidationError('Name is required', 'name');
}
if (!user.email) {
throw new ValidationError('Email is required', 'email');
}
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(user.email)) {
throw new ValidationError('Invalid email format', 'email');
}
return true;
}
function login(username, password) {
if (username !== 'admin' || password !== 'password') {
throw new AuthenticationError('Invalid credentials');
}
return 'Login successful';
}
// 使用自定义错误
try {
const user = { name: 'John' };
validateUser(user);
} catch (error) {
if (error instanceof ValidationError) {
console.error(`Validation error in ${error.field}: ${error.message}`);
} else {
console.error('Unexpected error:', error);
}
}3. Promise 错误处理
javascript
// Promise 错误处理
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(data => {
console.log('Data:', data);
})
.catch(error => {
console.error('Error:', error);
});
// Async/Await 错误处理
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log('Data:', data);
return data;
} catch (error) {
console.error('Error:', error);
// 可以重新抛出错误
throw error;
}
}最佳实践
1. 代码组织
- 使用模块化:将代码分割成多个模块,每个模块负责特定功能
- 遵循单一职责原则:每个函数或类只负责一个功能
- 保持代码简洁:避免不必要的复杂性,遵循 KISS 原则
- 使用有意义的命名:变量、函数和类的名称应该清晰表达其用途
- 添加注释:为复杂逻辑添加注释,提高代码可读性
2. 性能优化
- 避免全局变量:减少全局变量的使用,避免命名冲突和内存泄漏
- 使用事件委托:对于大量相似元素,使用事件委托减少事件监听器数量
- 实现防抖和节流:对于频繁触发的事件(如滚动、 resize),使用防抖和节流优化
- 优化循环:减少循环中的计算,避免在循环中操作 DOM
- 使用适当的数据结构:根据场景选择合适的数据结构,如 Map、Set 等
- 避免不必要的 DOM 操作:批量处理 DOM 操作,使用 DocumentFragment
- 使用 requestAnimationFrame:对于动画效果,使用 requestAnimationFrame 代替 setTimeout
3. 安全性
- 避免 eval:避免使用 eval() 执行字符串代码,防止代码注入攻击
- 使用严格模式:在脚本顶部添加
'use strict';,提高代码安全性 - 验证用户输入:对所有用户输入进行验证,防止 XSS 和 SQL 注入攻击
- 使用 HTTPS:在生产环境中使用 HTTPS,保护数据传输安全
- 设置适当的 CSP:使用 Content Security Policy 防止 XSS 攻击
- 避免使用 innerHTML:尽量使用 textContent 或 createElement 代替 innerHTML
- 使用安全的随机数:使用 crypto.getRandomValues() 生成安全的随机数
4. 代码风格
- 使用一致的缩进:选择 2 或 4 个空格作为缩进,保持一致
- 使用分号:虽然 JavaScript 允许省略分号,但为了代码一致性和避免意外行为,建议使用分号
- 使用单引号或双引号:选择一种引号风格并保持一致
- 使用箭头函数:对于简短的函数,使用箭头函数提高代码可读性
- 使用模板字符串:对于复杂的字符串拼接,使用模板字符串
- 使用解构赋值:对于对象和数组的赋值,使用解构赋值提高代码可读性
工具和框架
1. 包管理
json
{
"name": "my-project",
"version": "1.0.0",
"description": "My JavaScript project",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "jest",
"lint": "eslint .",
"build": "webpack"
},
"dependencies": {
"lodash": "^4.17.21",
"axios": "^1.6.0",
"express": "^4.18.2"
},
"devDependencies": {
"jest": "^29.7.0",
"eslint": "^8.55.0",
"prettier": "^3.1.1",
"nodemon": "^3.0.2",
"webpack": "^5.89.0",
"webpack-cli": "^5.1.4",
"babel-loader": "^9.1.3",
"@babel/core": "^7.23.6",
"@babel/preset-env": "^7.23.6"
}
}2. 代码质量工具
ESLint:代码质量检查工具
javascript
// .eslintrc.js
module.exports = {
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'eslint:recommended',
'prettier'
],
parserOptions: {
ecmaVersion: 12,
sourceType: 'module'
},
rules: {
'no-console': 'warn',
'no-unused-vars': 'error',
'prefer-const': 'error'
}
};Prettier:代码格式化工具
javascript
// .prettierrc.js
module.exports = {
semi: true,
trailingComma: 'es5',
singleQuote: true,
printWidth: 80,
tabWidth: 2
};3. 构建工具
Webpack:模块打包工具
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: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
},
devServer: {
static: {
directory: path.join(__dirname, 'public')
},
port: 3000,
hot: true
},
mode: 'development'
};Vite:现代前端构建工具
javascript
// vite.config.js
import { defineConfig } from 'vite';
export default defineConfig({
server: {
port: 3000
},
build: {
outDir: 'dist',
minify: 'terser'
}
});4. 测试工具
Jest:JavaScript 测试框架
javascript
// sum.test.js
const sum = require('./sum');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
test('adds negative numbers', () => {
expect(sum(-1, -2)).toBe(-3);
});Cypress:端到端测试工具
javascript
// cypress/e2e/homepage.cy.js
describe('Homepage', () => {
it('should load successfully', () => {
cy.visit('/');
cy.contains('Welcome to my website');
});
it('should have a working navigation', () => {
cy.visit('/');
cy.get('nav a').contains('About').click();
cy.url().should('include', '/about');
});
});实际应用场景
1. 数据处理
javascript
// 处理 API 响应数据
async function fetchAndProcessData() {
try {
const response = await fetch('https://api.example.com/users');
const users = await response.json();
// 处理数据
const activeUsers = users
.filter(user => user.status === 'active')
.map(user => ({
id: user.id,
fullName: `${user.firstName} ${user.lastName}`,
email: user.email,
registrationDate: new Date(user.createdAt).toLocaleDateString()
}))
.sort((a, b) => new Date(b.registrationDate) - new Date(a.registrationDate));
return activeUsers;
} catch (error) {
console.error('Error processing data:', error);
return [];
}
}2. 表单验证
javascript
// 表单验证
function validateForm(formData) {
const errors = {};
if (!formData.name) {
errors.name = 'Name is required';
}
if (!formData.email) {
errors.email = 'Email is required';
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
errors.email = 'Invalid email format';
}
if (!formData.password) {
errors.password = 'Password is required';
} else if (formData.password.length < 8) {
errors.password = 'Password must be at least 8 characters';
}
if (formData.password !== formData.confirmPassword) {
errors.confirmPassword = 'Passwords do not match';
}
return {
isValid: Object.keys(errors).length === 0,
errors
};
}
// 使用
const formData = {
name: 'John Doe',
email: 'john@example.com',
password: 'password123',
confirmPassword: 'password123'
};
const validation = validateForm(formData);
if (validation.isValid) {
console.log('Form is valid, submitting...');
} else {
console.log('Form errors:', validation.errors);
}3. 状态管理
javascript
// 简单的状态管理
class Store {
constructor(initialState) {
this.state = initialState;
this.listeners = [];
}
getState() {
return this.state;
}
setState(newState) {
this.state = { ...this.state, ...newState };
this.notifyListeners();
}
subscribe(listener) {
this.listeners.push(listener);
return () => {
this.listeners = this.listeners.filter(l => l !== listener);
};
}
notifyListeners() {
this.listeners.forEach(listener => listener(this.state));
}
}
// 使用
const initialState = {
user: null,
isLoading: false,
error: null
};
const store = new Store(initialState);
// 订阅状态变化
const unsubscribe = store.subscribe(state => {
console.log('State changed:', state);
});
// 更新状态
store.setState({ isLoading: true });
store.setState({ user: { name: 'John', email: 'john@example.com' }, isLoading: false });
// 取消订阅
unsubscribe();设计模式
1. 单例模式
javascript
// 单例模式:确保一个类只有一个实例
class Singleton {
constructor() {
if (Singleton.instance) {
return Singleton.instance;
}
this.data = [];
Singleton.instance = this;
}
addItem(item) {
this.data.push(item);
}
getItem(index) {
return this.data[index];
}
static getInstance() {
if (!Singleton.instance) {
Singleton.instance = new Singleton();
}
return Singleton.instance;
}
}
// 使用
const instance1 = new Singleton();
const instance2 = new Singleton();
console.log(instance1 === instance2); // true
const instance3 = Singleton.getInstance();
console.log(instance1 === instance3); // true2. 工厂模式
javascript
// 工厂模式:创建对象的接口,让子类决定实例化哪个类
class Product {
constructor(name) {
this.name = name;
}
display() {
return `Product: ${this.name}`;
}
}
class ConcreteProductA extends Product {
display() {
return `Concrete Product A: ${this.name}`;
}
}
class ConcreteProductB extends Product {
display() {
return `Concrete Product B: ${this.name}`;
}
}
class ProductFactory {
static createProduct(type, name) {
switch (type) {
case 'A':
return new ConcreteProductA(name);
case 'B':
return new ConcreteProductB(name);
default:
throw new Error('Invalid product type');
}
}
}
// 使用
const productA = ProductFactory.createProduct('A', 'Product 1');
const productB = ProductFactory.createProduct('B', 'Product 2');
console.log(productA.display()); // "Concrete Product A: Product 1"
console.log(productB.display()); // "Concrete Product B: Product 2"3. 观察者模式
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 update: ${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 World!');
// Output:
// Observer 1 received update: Hello World!
// Observer 2 received update: Hello World!
subject.unsubscribe(observer1);
subject.notify('Hello Again!');
// Output:
// Observer 2 received update: Hello Again!4. 装饰器模式
javascript
// 装饰器模式:动态地给对象添加额外的职责
class Component {
operation() {
return 'Component operation';
}
}
class Decorator {
constructor(component) {
this.component = component;
}
operation() {
return this.component.operation();
}
}
class ConcreteDecoratorA extends Decorator {
operation() {
return `ConcreteDecoratorA(${super.operation()})`;
}
}
class ConcreteDecoratorB extends Decorator {
operation() {
return `ConcreteDecoratorB(${super.operation()})`;
}
}
// 使用
const component = new Component();
const decoratorA = new ConcreteDecoratorA(component);
const decoratorB = new ConcreteDecoratorB(decoratorA);
console.log(component.operation()); // "Component operation"
console.log(decoratorA.operation()); // "ConcreteDecoratorA(Component operation)"
console.log(decoratorB.operation()); // "ConcreteDecoratorB(ConcreteDecoratorA(Component operation))"总结
现代 JavaScript 提供了丰富的特性和工具,从 ES6+ 的新语法到强大的异步编程模型,从函数式编程范式到面向对象编程,JavaScript 已经发展成为一门功能强大、灵活多变的编程语言。
通过掌握本文介绍的核心概念和最佳实践,你可以:
- 编写更简洁、更可读的代码:使用箭头函数、模板字符串、解构赋值、可选链操作符等现代特性
- 处理异步操作更优雅:使用 Promise 和 async/await 简化异步代码
- 构建更可维护的应用:使用模块化、单一职责原则、设计模式和良好的代码组织
- 提高代码性能:了解性能优化技巧,避免常见的性能陷阱
- 增强代码安全性:遵循安全最佳实践,防止常见的安全漏洞
- 使用现代数据结构:充分利用 Set、Map、WeakSet、WeakMap 等现代集合类型
- 应用设计模式:使用单例、工厂、观察者、装饰器等设计模式解决常见问题
JavaScript 的学习是一个持续的过程,随着 ECMAScript 规范的不断更新,新的特性和最佳实践也在不断涌现。保持学习的态度,不断实践和探索,你将能够充分发挥 JavaScript 的潜力,构建出更加优秀的 Web 应用。
参考资源
- MDN JavaScript 文档 - 权威的 JavaScript 参考文档
- JavaScript.info - 现代 JavaScript 教程
- ECMAScript 规范 - JavaScript 语言规范
- You Don't Know JS - 深入理解 JavaScript 的系列书籍
- JavaScript 设计模式 - JavaScript 设计模式指南
- Frontend Masters - 高质量的前端开发课程
- Stack Overflow - 解决 JavaScript 问题的社区
- Dev.to - 开发者社区,分享 JavaScript 相关文章