1. JavaScript语言基础与核心概念
JavaScript作为现代Web开发的基石语言,其基础语法和核心概念是每位开发者必须掌握的硬核技能。让我们从最基础的变量声明开始,逐步深入理解这门语言的精髓。
1.1 变量声明:var、let与const的进化史
在ES6之前,JavaScript只有var一种变量声明方式,这导致了许多令人困惑的作用域问题。ES6引入的let和const彻底改变了这一局面:
// 传统var声明 - 函数作用域 var x = 10; if (true) { var x = 20; // 同一个x! console.log(x); // 20 } console.log(x); // 20 // 现代let声明 - 块级作用域 let y = 10; if (true) { let y = 20; // 不同的y console.log(y); // 20 } console.log(y); // 10 // const声明 - 不可重新赋值 const z = 30; // z = 40; // 报错:Assignment to constant variable实际开发中,建议默认使用const,只有确实需要重新赋值的变量才使用let,基本可以完全避免使用var
1.2 数据类型与类型转换
JavaScript是动态类型语言,但理解其内部类型系统至关重要。主要数据类型包括:
- 原始类型:String、Number、Boolean、Null、Undefined、Symbol、BigInt
- 对象类型:Object(包括Array、Function等特殊对象)
类型转换是常见的痛点,特别是==和===的区别:
console.log(1 == '1'); // true - 宽松相等 console.log(1 === '1'); // false - 严格相等 // 显式类型转换最佳实践 const num = Number('123'); // 显式转为数字 const str = String(123); // 显式转为字符串 const bool = Boolean(''); // 显式转为布尔值(false)1.3 函数与作用域
JavaScript函数有多种定义方式,各有适用场景:
// 函数声明 - 会提升(hoisting) function add(a, b) { return a + b; } // 函数表达式 const multiply = function(a, b) { return a * b; }; // 箭头函数(ES6+) - 没有自己的this const divide = (a, b) => a / b; // 立即执行函数(IIFE) (function() { console.log('立即执行'); })();作用域链和闭包是JavaScript最强大的特性之一:
function createCounter() { let count = 0; // 闭包保护的变量 return { increment: () => ++count, get: () => count }; } const counter = createCounter(); console.log(counter.increment()); // 1 console.log(counter.get()); // 12. 面向对象与原型系统
2.1 原型链机制
JavaScript采用基于原型的面向对象模式,与传统的基于类的语言不同:
function Person(name) { this.name = name; } Person.prototype.greet = function() { return `Hello, ${this.name}!`; }; const john = new Person('John'); console.log(john.greet()); // Hello, John! // 原型链查找 console.log(john.toString()); // 来自Object.prototype2.2 ES6类语法糖
虽然底层仍是原型继承,但ES6的class语法更符合传统OOP开发者的习惯:
class Animal { constructor(name) { this.name = name; } speak() { console.log(`${this.name} makes a noise.`); } } class Dog extends Animal { constructor(name, breed) { super(name); this.breed = breed; } speak() { console.log(`${this.name} barks!`); } } const dog = new Dog('Rex', 'Labrador'); dog.speak(); // Rex barks!2.3 对象操作技巧
现代JavaScript提供了许多便捷的对象操作方法:
// 对象解构 const user = { id: 1, name: 'Alice', age: 25 }; const { name, age } = user; // 对象展开 const updatedUser = { ...user, age: 26 }; // 属性简写 const x = 10, y = 20; const point = { x, y }; // 可选链操作符(?.) console.log(user?.address?.street); // undefined而不报错 // 空值合并运算符(??) const displayName = user.nickname ?? user.name;3. 数组与迭代操作
3.1 数组方法大全
JavaScript数组提供了丰富的操作方法,可分为几大类:
变异方法(修改原数组):
const arr = [1, 2, 3]; arr.push(4); // 末尾添加 [1,2,3,4] arr.pop(); // 移除末尾 [1,2,3] arr.unshift(0); // 开头添加 [0,1,2,3] arr.shift(); // 移除开头 [1,2,3] arr.splice(1, 1); // 删除索引1开始的1个元素 [1,3]非变异方法(返回新数组):
const numbers = [1, 2, 3, 4]; const doubled = numbers.map(x => x * 2); // [2,4,6,8] const evens = numbers.filter(x => x % 2 === 0); // [2,4] const sum = numbers.reduce((acc, x) => acc + x, 0); // 10查找方法:
const users = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]; const bob = users.find(user => user.id === 2); const hasBob = users.some(user => user.name === 'Bob'); const allValid = users.every(user => user.id > 0);3.2 迭代器与生成器
ES6引入的迭代协议为集合操作提供了统一接口:
// 自定义可迭代对象 const myIterable = { *[Symbol.iterator]() { yield 1; yield 2; yield 3; } }; for (const value of myIterable) { console.log(value); // 1, 2, 3 } // 生成器函数 function* idGenerator() { let id = 1; while (true) { yield id++; } } const gen = idGenerator(); console.log(gen.next().value); // 1 console.log(gen.next().value); // 24. 异步编程演进
4.1 回调地狱与Promise
从回调函数到Promise的演进解决了著名的"回调地狱"问题:
// 传统回调方式 function fetchData(callback) { setTimeout(() => { callback('Data loaded'); }, 1000); } fetchData(data => { console.log(data); fetchMoreData(moreData => { console.log(moreData); // 更多嵌套... }); }); // Promise方式 function fetchData() { return new Promise(resolve => { setTimeout(() => resolve('Data loaded'), 1000); }); } fetchData() .then(data => { console.log(data); return fetchMoreData(); }) .then(moreData => { console.log(moreData); }) .catch(error => { console.error(error); });4.2 async/await革命
ES2017引入的async/await让异步代码看起来像同步代码:
async function loadAllData() { try { const data = await fetchData(); console.log(data); const moreData = await fetchMoreData(); console.log(moreData); return processData(data, moreData); } catch (error) { console.error('Failed to load:', error); throw error; } } // 立即执行async函数 (async () => { const result = await loadAllData(); console.log('Final result:', result); })();4.3 现代异步模式
结合Promise的静态方法和新的语言特性:
// 并行执行 const [user, posts] = await Promise.all([ fetchUser(userId), fetchPosts(userId) ]); // 竞速模式 const data = await Promise.race([ fetchFromPrimary(), fetchFromSecondary() ]); // 错误处理改进 try { const result = await fetchData().catch(err => { console.log('Fetch failed, using fallback'); return fallbackData; }); console.log(result); } catch (error) { // 处理其他错误 }5. DOM操作与事件系统
5.1 高效DOM查询
现代DOM查询API已经非常丰富:
// 获取单个元素 const header = document.getElementById('header'); const button = document.querySelector('.btn-primary'); // 获取元素集合 const allButtons = document.querySelectorAll('button'); const listItems = document.getElementsByClassName('list-item'); // 遍历优化 const buttonsArray = Array.from(allButtons); // 转为真数组 buttonsArray.forEach(btn => { btn.classList.add('processed'); }); // 新的便捷方法 const form = document.querySelector('form'); form.elements.email.focus(); // 直接聚焦到email字段5.2 事件处理最佳实践
事件处理是交互式Web应用的核心:
// 事件委托 - 高效处理动态内容 document.getElementById('list').addEventListener('click', event => { if (event.target.classList.contains('item')) { console.log('Item clicked:', event.target.dataset.id); } }); // 自定义事件 const event = new CustomEvent('itemAdded', { detail: { productId: 123 }, bubbles: true }); document.dispatchEvent(event); // 一次性事件 button.addEventListener('click', function handleClick() { console.log('Button clicked - removing listener'); button.removeEventListener('click', handleClick); }, { once: true }); // 被动事件提升滚动性能 window.addEventListener('scroll', () => { console.log('Scrolling'); }, { passive: true });5.3 动态样式操作
现代CSS-in-JS方案的基础:
// classList API element.classList.add('active'); element.classList.remove('hidden'); element.classList.toggle('visible'); // 直接样式操作 element.style.setProperty('--primary-color', '#4285f4'); element.style.backgroundColor = 'transparent'; // 获取计算样式 const styles = window.getComputedStyle(element); console.log(styles.getPropertyValue('font-size')); // CSSOM操作 const sheet = document.styleSheets[0]; sheet.insertRule(`.btn:hover { background: ${hoverColor} }`, sheet.cssRules.length);6. 现代JavaScript开发实践
6.1 模块化开发
ES Modules已成为JavaScript标准模块系统:
// math.js export const PI = 3.14159; export function sum(a, b) { return a + b; } export default class Calculator { /*...*/ } // app.js import Calculator, { PI, sum } from './math.js'; import * as math from './math.js'; // 命名空间导入 // 动态导入 async function loadModule() { const module = await import('./dynamic-module.js'); module.doSomething(); }6.2 错误处理策略
健壮的错误处理是专业开发的标志:
// 基本try-catch try { riskyOperation(); } catch (error) { console.error('Operation failed:', error); // 恢复或上报错误 reportError(error); } finally { cleanup(); } // Promise错误处理 fetchData() .then(process) .catch(error => { if (error instanceof NetworkError) { retry(); } else { showErrorMessage(error); } }); // 全局错误处理 window.addEventListener('error', event => { trackError(event.error); }); // 未处理的Promise拒绝 window.addEventListener('unhandledrejection', event => { console.warn('Unhandled rejection:', event.reason); });6.3 性能优化技巧
JavaScript性能关键点:
// 防抖与节流 function debounce(func, delay) { let timeout; return (...args) => { clearTimeout(timeout); timeout = setTimeout(() => func(...args), delay); }; } const throttledScroll = throttle(() => { console.log('Scroll event'); }, 200); window.addEventListener('scroll', throttledScroll); // Web Worker const worker = new Worker('worker.js'); worker.postMessage({ task: 'processData', data: largeData }); worker.onmessage = ({ data }) => { console.log('Result from worker:', data); }; // 内存管理 const dataCache = new WeakMap(); // 弱引用缓存 function processLargeObject(obj) { if (dataCache.has(obj)) { return dataCache.get(obj); } const result = expensiveCalculation(obj); dataCache.set(obj, result); return result; }7. 测试与调试
7.1 浏览器开发者工具技巧
现代浏览器提供了强大的调试能力:
// 条件断点 function processItems(items) { for (const item of items) { // 右键行号添加条件断点:item.id === 42 console.log(item); } } // console高级用法 console.table(users); // 表格化输出 console.time('fetch'); await fetchData(); console.timeEnd('fetch'); // 计时 // 调试函数 debugger; // 触发断点 function complexCalculation() { // 可以在控制台直接调用此函数进行测试 } // 性能分析 console.profile('My Function'); myFunction(); console.profileEnd('My Function');7.2 单元测试实践
使用现代测试框架编写可维护的测试:
// 使用Jest测试框架示例 describe('math utilities', () => { beforeAll(() => { // 初始化 }); test('sum adds numbers correctly', () => { expect(sum(1, 2)).toBe(3); expect(sum(-1, 1)).toBe(0); }); test('divide handles zero correctly', () => { expect(() => divide(1, 0)).toThrow('Cannot divide by zero'); }); // 快照测试 test('render component correctly', () => { const component = render(<MyComponent />); expect(component).toMatchSnapshot(); }); });7.3 类型检查与TypeScript
JavaScript的类型系统增强:
// TypeScript基础 interface User { id: number; name: string; email?: string; // 可选属性 } function greetUser(user: User): string { return `Hello, ${user.name}!`; } // 泛型 function identity<T>(arg: T): T { return arg; } // 类型推断 const users: User[] = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]; // JSDoc类型注释(纯JavaScript也可用) /** * @param {number} a * @param {number} b * @returns {number} */ function add(a, b) { return a + b; }8. 安全与最佳实践
8.1 常见安全漏洞防范
前端开发中的安全要点:
// XSS防护 function safeHtml(str) { const div = document.createElement('div'); div.textContent = str; return div.innerHTML; } // CSRF防护 fetch('/api/data', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': getCSRFToken() }, body: JSON.stringify(data) }); // 内容安全策略(CSP) <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline'"> // 安全的JSON解析 function safeJsonParse(str) { try { return JSON.parse(str); } catch { return null; } }8.2 代码质量工具
保持代码一致性和质量:
// ESLint配置示例(.eslintrc.js) module.exports = { extends: ['eslint:recommended', 'plugin:prettier/recommended'], rules: { 'no-var': 'error', 'prefer-const': 'warn', 'no-unused-vars': ['error', { argsIgnorePattern: '^_' }] }, env: { browser: true, es2021: true } }; // Prettier配置(.prettierrc) { "semi": false, "singleQuote": true, "printWidth": 100, "trailingComma": "es5" } // Git钩子配合Husky { "husky": { "hooks": { "pre-commit": "lint-staged" } }, "lint-staged": { "*.js": ["eslint --fix", "prettier --write"] } }8.3 现代化工作流
现代JavaScript开发环境:
# 使用npm脚本 { "scripts": { "start": "webpack serve --mode development", "build": "webpack --mode production", "test": "jest", "lint": "eslint .", "format": "prettier --write ." } } # 常用开发依赖 npm install --save-dev webpack webpack-cli babel-loader @babel/core @babel/preset-env eslint prettier jest # 现代浏览器API垫片 import 'core-js/stable'; import 'regenerator-runtime/runtime';9. 前端框架集成
9.1 React中的JavaScript
现代React开发模式:
// React组件示例 import React, { useState, useEffect } from 'react'; function Counter() { const [count, setCount] = useState(0); useEffect(() => { document.title = `Count: ${count}`; return () => { // 清理effect }; }, [count]); const increment = useCallback(() => { setCount(c => c + 1); }, []); return ( <div> <p>Current count: {count}</p> <button onClick={increment}>Increment</button> </div> ); } // 自定义Hook function useLocalStorage(key, initialValue) { const [value, setValue] = useState(() => { const stored = localStorage.getItem(key); return stored !== null ? JSON.parse(stored) : initialValue; }); useEffect(() => { localStorage.setItem(key, JSON.stringify(value)); }, [key, value]); return [value, setValue]; }9.2 Vue中的JavaScript
Vue 3的组合式API:
import { ref, computed, watch, onMounted } from 'vue'; export default { setup() { const count = ref(0); const double = computed(() => count.value * 2); function increment() { count.value++; } watch(count, (newVal, oldVal) => { console.log(`Count changed from ${oldVal} to ${newVal}`); }); onMounted(() => { console.log('Component mounted'); }); return { count, double, increment }; } };9.3 状态管理方案
现代状态管理库的使用:
// Redux Toolkit示例 import { configureStore, createSlice } from '@reduxjs/toolkit'; const counterSlice = createSlice({ name: 'counter', initialState: { value: 0 }, reducers: { incremented: state => { state.value++; }, decremented: state => { state.value--; } } }); const store = configureStore({ reducer: { counter: counterSlice.reducer } }); // 使用 store.dispatch(counterSlice.actions.incremented()); console.log(store.getState().counter.value);10. 高级主题与未来趋势
10.1 Web Assembly集成
JavaScript与WebAssembly的互操作:
// 加载WASM模块 async function loadWasm() { const response = await fetch('module.wasm'); const buffer = await response.arrayBuffer(); const module = await WebAssembly.compile(buffer); const instance = await WebAssembly.instantiate(module); return instance.exports; } // 使用WASM函数 const wasm = await loadWasm(); const result = wasm.compute(42); console.log('WASM result:', result);10.2 Web Workers多线程
利用多核CPU的并行计算:
// 主线程 const worker = new Worker('worker.js'); worker.postMessage({ task: 'process', data: largeArray }); worker.onmessage = ({ data }) => { console.log('Result:', data); }; // worker.js self.onmessage = ({ data }) => { const result = intensiveComputation(data.data); self.postMessage(result); };10.3 渐进式Web应用(PWA)
构建可离线工作的Web应用:
// service-worker.js self.addEventListener('install', event => { event.waitUntil( caches.open('v1').then(cache => { return cache.addAll([ '/', '/index.html', '/styles.css', '/app.js' ]); }) ); }); self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request).then(response => { return response || fetch(event.request); }) ); }); // 注册Service Worker if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker.register('/service-worker.js'); }); }10.4 Web Components
原生组件化方案:
// 定义自定义元素 class MyElement extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); } connectedCallback() { this.shadowRoot.innerHTML = ` <style> :host { display: block; padding: 16px; } </style> <div>Hello, <slot></slot>!</div> `; } } customElements.define('my-element', MyElement); // 使用 <my-element>World</my-element>11. 实用代码片段库
11.1 日期时间处理
// 日期格式化 function formatDate(date, format = 'YYYY-MM-DD') { const pad = n => n.toString().padStart(2, '0'); return format .replace(/YYYY/g, date.getFullYear()) .replace(/MM/g, pad(date.getMonth() + 1)) .replace(/DD/g, pad(date.getDate())) .replace(/HH/g, pad(date.getHours())) .replace(/mm/g, pad(date.getMinutes())) .replace(/ss/g, pad(date.getSeconds())); } // 相对时间 function timeAgo(date) { const seconds = Math.floor((new Date() - date) / 1000); const intervals = { year: 31536000, month: 2592000, week: 604800, day: 86400, hour: 3600, minute: 60 }; for (const [unit, secondsInUnit] of Object.entries(intervals)) { const interval = Math.floor(seconds / secondsInUnit); if (interval >= 1) { return `${interval} ${unit}${interval === 1 ? '' : 's'} ago`; } } return 'just now'; }11.2 字符串处理
// 安全HTML转义 function escapeHtml(unsafe) { return unsafe .replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } // 生成随机字符串 function randomString(length = 8) { return Array.from(crypto.getRandomValues(new Uint8Array(length))) .map(b => b.toString(16).padStart(2, '0')) .join('') .slice(0, length); } // 字符串模板引擎 function renderTemplate(template, data) { return template.replace(/\${([^}]+)}/g, (_, key) => { return data[key.trim()] || ''; }); }11.3 数据结构操作
// 深度克隆对象 function deepClone(obj) { if (obj === null || typeof obj !== 'object') return obj; if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj); const clone = Array.isArray(obj) ? [] : {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { clone[key] = deepClone(obj[key]); } } return clone; } // 对象深度合并 function deepMerge(target, source) { if (typeof target !== 'object' || typeof source !== 'object') return source; for (const key in source) { if (source.hasOwnProperty(key)) { if (key in target) { target[key] = deepMerge(target[key], source[key]); } else { target[key] = deepClone(source[key]); } } } return target; }12. 调试与性能优化实战
12.1 内存泄漏检测
常见内存泄漏模式及解决方案:
// 1. 未清理的定时器 function startTimer() { this.timer = setInterval(() => { console.log('Tick'); }, 1000); } // 正确做法 - 组件卸载时清理 function cleanup() { clearInterval(this.timer); } // 2. DOM引用未释放 const elements = []; function registerElement(element) { elements.push(element); } // 正确做法 - 使用WeakMap const elementMap = new WeakMap(); function safeRegister(element) { elementMap.set(element, { registered: true }); } // 3. 闭包意外保留 function createHeavyClosure() { const largeData = new Array(1000000).fill('data'); return function() { console.log('Closure executed'); // 意外保留了largeData引用 }; } // 正确做法 - 显式释放 function createLightClosure() { const largeData = new Array(1000000).fill('data'); return function() { console.log('Closure executed'); largeData.length = 0; // 显式释放 }; }12.2 性能分析工具
使用浏览器Performance API进行精细测量:
// 精确测量函数执行时间 function measure(fn) { const start = performance.now(); fn(); const end = performance.now(); console.log(`Execution time: ${(end - start).toFixed(2)}ms`); } // 内存使用分析 function logMemoryUsage() { if (window.performance?.memory) { const { usedJSHeapSize, totalJSHeapSize } = performance.memory; console.log(`Memory: ${(usedJSHeapSize / 1024 / 1024).toFixed(2)}MB / ${(totalJSHeapSize / 1024 / 1024).toFixed(2)}MB`); } } // 长任务监控 const observer = new PerformanceObserver(list => { for (const entry of list.getEntries()) { console.log('Long task:', entry.duration); } }); observer.observe({ entryTypes: ['longtask'] });12.3 代码分割与懒加载
优化大型应用加载性能:
// 动态导入实现代码分割 const loadModule = async () => { const module = await import('./heavyModule.js'); module.init(); }; // React懒加载组件 const LazyComponent = React.lazy(() => import('./LazyComponent')); function MyApp() { return ( <React.Suspense fallback={<div>Loading...</div>}> <LazyComponent /> </React.Suspense> ); } // 路由级代码分割 const routes = [ { path: '/dashboard', component: React.lazy(() => import('./Dashboard')) }, { path: '/settings', component: React.lazy(() => import('./Settings')) } ];13. 现代浏览器API应用
13.1 Web Storage与IndexedDB
客户端存储解决方案:
// localStorage封装 const storage = { get(key) { try { return JSON.parse(localStorage.getItem(key)); } catch { return null; } }, set(key, value) { localStorage.setItem(key, JSON.stringify(value)); }, remove(key) { localStorage.removeItem(key); } }; // IndexedDB操作 function openDatabase(name, version, upgradeCallback) { return new Promise((resolve, reject) => { const request = indexedDB.open(name, version); request.onerror = () => reject(request.error); request.onsuccess = () => resolve(request.result); request.onupgradeneeded = event => { upgradeCallback(event.target.result, event.oldVersion); }; }); } // 使用示例 const db = await openDatabase('my-db', 1, db => { if (!db.objectStoreNames.contains('users')) { db.createObjectStore('users', { keyPath: 'id' }); } });13.2 地理位置与传感器API
// 获取地理位置 function getLocation() { return new Promise((resolve, reject) => { if (!navigator.geolocation) { reject(new Error('Geolocation not supported')); } navigator.geolocation.getCurrentPosition( position => resolve(position.coords), error => reject(error), { enableHighAccuracy: true, timeout: 5000 } ); }); } // 设备方向检测 function setupOrientation() { if (window.DeviceOrientationEvent) { window.addEventListener('deviceorientation', event => { console.log('Alpha:', event.alpha); // 绕Z轴旋转 console.log('Beta:', event.beta); // 绕X轴旋转 console.log('Gamma:', event.gamma); // 绕Y轴旋转 }); } } // 光线传感器 if ('AmbientLightSensor' in window) { const sensor = new AmbientLightSensor(); sensor.onreading = () => { document.body.style.backgroundColor = sensor.illuminance < 50 ? 'black' : 'white'; }; sensor.start(); }13.3 剪贴板与文件API
// 剪贴板操作 async function copyToClipboard(text) { try { await navigator.clipboard.writeText(text); console.log('Copied to clipboard'); } catch (err) { console.error('Failed to copy:', err); } } // 文件读取 function readFile(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => resolve(reader.result); reader.onerror = () => reject(reader.error); if (file.type.startsWith('image/')) { reader.readAsDataURL(file); } else { reader.readAsText(file); } }); } // 文件系统访问API async function saveFile(content) { try { const handle = await window.showSaveFilePicker({ types: [{ description: 'Text Files', accept: { 'text/plain': ['.txt'] } }] }); const writable = await handle.createWritable(); await writable.write(content); await writable.close(); } catch (err) { console.error('File save failed:', err); } }14. Node.js与全栈JavaScript
14.1 常用Node.js模块
核心模块的现代用法:
// 文件系统Promise API import { promises as fs } from 'fs'; async function processFiles() { try { const files = await fs.readdir('./data'); const contents = await Promise.all( files.map(file => fs.readFile(`./data/${file}`, 'utf8')) ); await fs.writeFile('./output.json', JSON.stringify(contents)); } catch (err) { console.error('File processing failed:', err); } } // 流处理大文件 import { createReadStream, createWriteStream } from 'fs'; import { pipeline } from 'stream/promises'; import { createGzip } from 'zlib'; async function compressFile(input, output) { await pipeline( createReadStream(input), createGzip(), createWriteStream(output) ); }14.2 Express.js中间件开发
import express from 'express'; import helmet from 'helmet'; import rateLimit from 'express-rate-limit'; const app = express(); // 安全中间件 app.use(helmet()); app.use(express.json({ limit: '10kb' })); // 速率限制 const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15分钟 max: 100 // 每个IP限制100个请求 }); app.use('/api', limiter); // 自定义中间件 app.use((req, res, next) => { req.startTime = Date.now(); res.on('finish', () => { console.log(`${req.method} ${req.path} - ${res.statusCode} [${Date.now() - req.startTime}ms]`); }); next(); }); // 错误处理中间件 app.use((err, req, res, next) => { console.error(err.stack); res.status(500).json({ error: 'Something went wrong!' }); });14.3 数据库交互
使用ORM进行数据库操作:
// Sequelize示例 import { Sequelize, Model, DataTypes } from 'sequelize'; const sequelize = new Sequelize('database', 'user', 'pass', { host: 'localhost', dialect: 'mysql' }); class User extends Model {} User.init({ username: DataTypes.STRING, email: { type: DataTypes.STRING, allowNull: false, unique: true } }, { sequelize, modelName: 'user' }); // 使用示例 async function createUser(userData) { try { await sequelize.authenticate(); await User.sync(); const user = await User.create(userData); return user; } catch (error) { console.error('Database error:', error); throw error; } }15. 测试驱动开发(TDD)实践
15.1 单元测试编写
// 使用Jest进行TDD function sum(a, b) { if (typeof a !== 'number' || typeof b !== 'number') { throw new TypeError('Arguments must be numbers'); } return a + b; } describe('sum function', () => {