1. JavaScript 核心三要素:语法、DOM与BOM全景解析
十年前我刚接触前端开发时,面对JavaScript的三大核心概念——语法基础、DOM操作和BOM接口,曾走过不少弯路。本文将用实战视角系统梳理这些核心知识点,特别分享那些官方文档不会告诉你的"生存技巧"。比如为什么[] == ![]会返回true?DOM操作如何避免"重排风暴"?BOM中哪些API存在严重的浏览器兼容问题?这些经验都来自我处理过的真实线上事故。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. JavaScript语法:从"奇怪行为"到精通之路
2.1 语法基础中的七个"陷阱"
JavaScript的语法看似简单,但隐藏着许多反直觉的特性。以下是新手最容易踩坑的典型场景:
-
自动分号插入(ASI):
以下代码会返回undefined而非对象:javascript复制function getObj() { return { name: 'test' } }这是因为引擎在return后自动插入了分号。解决方案是永远保持左花括号与return在同一行。
-
隐式类型转换:
当看到[] == ![]结果为true时,多数开发者会感到困惑。这涉及到ToPrimitive抽象操作的转换规则:![]先被转为false(逻辑非转换)- 比较时
[]通过valueOf()和toString()转为""(空字符串) - ""最终被转为数值0,false也转为0
-
变量提升与暂时性死区:
var存在变量提升,而let/const有暂时性死区(TDZ)。实战中建议:javascript复制// 反模式 console.log(x); // undefined var x = 10; // 推荐模式 const y = 20; // 提前声明并初始化
2.2 函数与作用域的实战要点
闭包的经典应用场景
javascript复制// 防抖函数实现
function debounce(fn, delay) {
let timer; // 闭包保存timer
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
关键点:闭包中的timer变量会被所有调用共享,这是实现防抖的核心
this绑定的四种规则优先级(从低到高):
- 默认绑定(全局对象,严格模式为undefined)
- 隐式绑定(通过对象调用)
- 显式绑定(call/apply/bind)
- new绑定(构造函数调用)
2.3 异步编程的演进史
从回调地狱到async/await的完整解决方案:
javascript复制// 回调地狱
getUser(id, function(user) {
getPosts(user, function(posts) {
showPosts(posts, function() {
// 更多嵌套...
});
});
});
// Promise改进
getUser(id)
.then(user => getPosts(user))
.then(posts => showPosts(posts))
.catch(err => console.error(err));
// async/await终极方案
async function displayUserPosts() {
try {
const user = await getUser(id);
const posts = await getPosts(user);
await showPosts(posts);
} catch (err) {
console.error(err);
}
}
3. DOM操作:性能优化与安全实践
3.1 高效DOM查询的黄金法则
javascript复制// 糟糕实践 - 重复查询
for (let i = 0; i < 100; i++) {
document.querySelector('.item'); // 每次循环都重新查询
}
// 最佳实践 - 缓存引用
const items = document.querySelectorAll('.item');
for (let i = 0; i < items.length; i++) {
// 使用已缓存的DOM引用
}
选择器性能对比(Chrome 115实测):
| 选择器类型 | 执行时间(10万次) |
|---|---|
| getElementById | 12ms |
| querySelector | 85ms |
| getElementsByClassName | 28ms |
| querySelectorAll | 92ms |
3.2 避免重排与重绘的六大策略
-
批量DOM修改:使用文档片段(documentFragment)
javascript复制const fragment = document.createDocumentFragment(); for (let i = 0; i < 100; i++) { const div = document.createElement('div'); fragment.appendChild(div); } document.body.appendChild(fragment); -
GPU加速:对动画元素使用transform和opacity
css复制.animate { transform: translateZ(0); will-change: transform; } -
读写分离:避免交替进行样式读取和写入
javascript复制// 错误方式 element.style.width = '100px'; const height = element.clientHeight; element.style.height = height + 'px'; // 正确方式 element.style.width = '100px'; element.style.height = '200px'; const height = element.clientHeight; // 所有写操作完成后统一读取
3.3 DOM安全:XSS防御实战
DOM型XSS防护方案:
javascript复制// 危险!直接插入未转义内容
element.innerHTML = userInput;
// 安全方案1:文本节点
element.textContent = userInput;
// 安全方案2:DOMPurify过滤
import DOMPurify from 'dompurify';
element.innerHTML = DOMPurify.sanitize(userInput);
4. BOM核心API与浏览器兼容性破解
4.1 导航与URL操作的黑科技
javascript复制// 获取当前URL参数(兼容IE10+)
const params = new URLSearchParams(window.location.search);
const id = params.get('id');
// 修改URL不刷新页面
window.history.pushState({id: 123}, '', '?id=123');
// 监听前进/后退
window.addEventListener('popstate', (e) => {
console.log('导航变化', e.state);
});
4.2 定时器的高级用法
javascript复制// 精确计时器(解决setInterval漂移问题)
function accurateInterval(callback, interval) {
let expected = Date.now() + interval;
const timeout = setTimeout(handler, interval);
function handler() {
const drift = Date.now() - expected;
callback();
expected += interval;
timeout = setTimeout(handler, Math.max(0, interval - drift));
}
return {
clear: () => clearTimeout(timeout)
};
}
4.3 存储方案的选型指南
| 方案 | 容量 | 生命周期 | 访问域 | 典型应用场景 |
|---|---|---|---|---|
| Cookie | 4KB | 可设置过期时间 | 同域 | 身份认证 |
| localStorage | 5-10MB | 永久 | 同源 | 持久化配置 |
| sessionStorage | 5-10MB | 会话结束清除 | 同源 | 表单临时保存 |
| IndexedDB | ≥50%磁盘 | 永久 | 同源 | 离线应用数据 |
javascript复制// IndexedDB事务最佳实践
const request = indexedDB.open('myDB', 2);
request.onupgradeneeded = (e) => {
const db = e.target.result;
if (!db.objectStoreNames.contains('books')) {
db.createObjectStore('books', { keyPath: 'isbn' });
}
};
request.onsuccess = (e) => {
const db = e.target.result;
const tx = db.transaction('books', 'readwrite');
const store = tx.objectStore('books');
store.put({ isbn: '9787121377965', title: 'JavaScript高级程序设计' });
tx.oncomplete = () => db.close();
};
5. 现代JavaScript开发必备工具链
5.1 调试技巧进阶
Chrome DevTools 高级功能:
- 条件断点:右键点击行号选择"Add conditional breakpoint"
- 日志点:无需暂停执行的console.log(右键选择"Add logpoint")
- 性能监控:Performance面板录制分析运行时性能
javascript复制// 在源码中插入debugger语句
function calculate(data) {
debugger; // 执行到此会自动暂停
return data.reduce((a, b) => a + b.value, 0);
}
5.2 模块化演进与打包优化
三种模块规范对比:
javascript复制// CommonJS (Node.js)
const lodash = require('lodash');
module.exports = {};
// ES Module (浏览器原生支持)
import lodash from 'lodash';
export default {};
// UMD (通用模块定义)
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
define(['lodash'], factory);
} else if (typeof module === 'object' && module.exports) {
module.exports = factory(require('lodash'));
} else {
root.myLib = factory(root._);
}
})(typeof self !== 'undefined' ? self : this, function(_) {
return {};
});
5.3 类型系统:从JS到TS的平滑迁移
typescript复制// 渐进式类型注解
function greet(name: string): string {
return `Hello, ${name}`;
}
// 接口与类型别名
interface User {
id: number;
name: string;
}
type Admin = User & {
privileges: string[];
};
// 泛型应用
function identity<T>(arg: T): T {
return arg;
}
6. 性能优化全链路实践
6.1 代码层面优化
javascript复制// 避免在循环中创建函数
// 反模式
for (var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i); // 总是输出10
}, 100);
}
// 解决方案1:使用let
for (let i = 0; i < 10; i++) {
setTimeout(() => console.log(i), 100);
}
// 解决方案2:IIFE
for (var i = 0; i < 10; i++) {
(function(j) {
setTimeout(() => console.log(j), 100);
})(i);
}
6.2 网络加载优化
关键优化指标:
- Time to First Byte (TTFB) < 200ms
- First Contentful Paint (FCP) < 1.8s
- Largest Contentful Paint (LCP) < 2.5s
html复制<!-- 资源加载策略 -->
<script src="critical.js" defer></script>
<link rel="preload" href="font.woff2" as="font" crossorigin>
6.3 内存管理实战
javascript复制// 内存泄漏检测
function detectMemoryLeak() {
const heapUsed = process.memoryUsage().heapUsed / 1024 / 1024;
console.log(`Heap used: ${heapUsed.toFixed(2)} MB`);
}
// 定时执行检测
setInterval(detectMemoryLeak, 5000);
// 常见泄漏场景1:未清理的定时器
const timer = setInterval(() => {}, 1000);
// 需要时清除
clearInterval(timer);
// 常见泄漏场景2:DOM引用未释放
const elements = {
button: document.getElementById('myButton')
};
// 需要时删除引用
delete elements.button;
7. 跨平台开发方案选型
7.1 Electron桌面端开发要点
javascript复制// 主进程与渲染进程通信
// main.js
const { ipcMain } = require('electron');
ipcMain.handle('get-data', async () => {
return await fetchData();
});
// renderer.js
const { ipcRenderer } = require('electron');
const data = await ipcRenderer.invoke('get-data');
7.2 React Native移动端适配技巧
javascript复制// 平台特定代码
if (Platform.OS === 'ios') {
// iOS特有实现
} else {
// Android实现
}
// 性能优化:避免内联函数
const renderItem = useCallback(({ item }) => (
<View style={styles.item}>
<Text>{item.title}</Text>
</View>
), []);
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
7.3 WebAssembly加速方案
javascript复制// C++代码编译为wasm
// example.cpp
extern "C" {
int add(int a, int b) {
return a + b;
}
}
// JavaScript调用
const response = await fetch('example.wasm');
const buffer = await response.arrayBuffer();
const module = await WebAssembly.instantiate(buffer);
console.log(module.instance.exports.add(2, 3)); // 输出5
8. 前沿技术演进与学习路径
8.1 ECMAScript新特性实践
javascript复制// 可选链操作符(?.)
const street = user?.address?.street;
// 空值合并运算符(??)
const timeout = settings.timeout ?? 3000;
// 顶层await
const data = await fetchData();
export { data };
// 私有字段
class Person {
#age = 0;
getAge() { return this.#age; }
}
8.2 Web Components开发模式
javascript复制// 自定义元素定义
class MyElement extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
this.shadowRoot.innerHTML = `
<style>
:host { display: block; }
</style>
<slot></slot>
`;
}
}
customElements.define('my-element', MyElement);
8.3 可视化与图形编程
javascript复制// Canvas性能优化
function draw() {
requestAnimationFrame(draw);
// 使用离屏Canvas
offscreenCtx.clearRect(0, 0, width, height);
// ...绘制逻辑
ctx.drawImage(offscreenCanvas, 0, 0);
}
// WebGL基础示例
const gl = canvas.getContext('webgl');
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
9. 企业级项目架构设计
9.1 状态管理方案对比
| 方案 | 学习曲线 | 适用场景 | 典型应用 |
|---|---|---|---|
| Redux | 陡峭 | 复杂状态交互 | 管理面板 |
| MobX | 平缓 | 响应式需求 | 实时数据展示 |
| Context API | 中等 | 简单全局状态 | 主题/用户信息 |
| Recoil | 中等 | 原子化状态 | 大型应用 |
javascript复制// Redux Toolkit现代写法
import { configureStore, createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: state => { state.value += 1; },
},
});
const store = configureStore({
reducer: {
counter: counterSlice.reducer,
},
});
9.2 微前端架构实践
javascript复制// 模块联邦配置(Webpack 5)
// app1/webpack.config.js
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'app1',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/Button',
},
}),
],
};
// app2/webpack.config.js
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'app2',
remotes: {
app1: 'app1@http://localhost:3001/remoteEntry.js',
},
}),
],
};
9.3 测试策略与质量保障
javascript复制// Jest单元测试示例
function sum(a, b) {
return a + b;
}
describe('sum function', () => {
it('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
// 快照测试
it('renders correctly', () => {
const component = renderer.create(<MyComponent />);
expect(component.toJSON()).toMatchSnapshot();
});
});
// Cypress端到端测试
describe('Login Test', () => {
it('successfully logs in', () => {
cy.visit('/login');
cy.get('#username').type('user');
cy.get('#password').type('pass');
cy.get('form').submit();
cy.url().should('include', '/dashboard');
});
});
10. 开发者成长与资源推荐
10.1 高效学习路线图
JavaScript精通路径:
- 基础语法(2周)
- 变量与作用域
- 函数与闭包
- 原型与继承
- 核心API(3周)
- DOM/BOM操作
- 事件循环机制
- 异步编程模式
- 工程化(4周)
- 模块化开发
- 构建工具链
- 测试与部署
- 高阶主题(持续学习)
- 性能优化
- 设计模式
- 架构设计
10.2 必读书目与课程
纸质书推荐:
- 《JavaScript高级程序设计》(第4版)- 全面系统
- 《你不知道的JavaScript》系列 - 深入原理
- 《JavaScript设计模式》- 架构思维
在线资源:
- MDN Web Docs(最权威参考)
- JavaScript.info(交互式教程)
- Frontend Masters(付费高质量课程)
10.3 开发者工具精选
VS Code插件组合:
- ESLint - 代码规范检查
- Prettier - 自动格式化
- Debugger for Chrome - 调试
- GitLens - 版本控制增强
- REST Client - API测试
命令行工具:
bash复制# 代码质量检查
npx eslint src/
# 打包分析
npx source-map-explorer bundle.js
# 性能测试
npx lighthouse http://example.com
11. 疑难问题排查手册
11.1 常见错误代码速查
| 错误类型 | 可能原因 | 解决方案 |
|---|---|---|
| Cannot read property | 对象未初始化 | 添加空值检查 obj?.property |
| undefined is not a function | 方法不存在 | 检查原型链或polyfill |
| Unexpected token | 语法错误或缺少转译 | 检查Babel/TS配置 |
| Maximum call stack | 递归未终止 | 添加基线条件 |
| Failed to load resource | CORS限制 | 配置服务器Access-Control-Allow-Origin |
11.2 调试技巧汇编
Chrome DevTools 高级技巧:
- 条件断点:右键行号设置条件
- 日志点:无需暂停的console.log
- 性能分析:录制并分析运行时瓶颈
- 内存快照:查找内存泄漏
- 覆盖统计:检查未使用的代码
javascript复制// 控制台高级用法
console.table([
{ name: 'John', age: 25 },
{ name: 'Jane', age: 30 }
]);
// 性能计时
console.time('fetch');
await fetchData();
console.timeEnd('fetch'); // 输出耗时
11.3 浏览器兼容性解决方案
Polyfill自动加载方案:
html复制<script src="https://polyfill.io/v3/polyfill.min.js?features=es2015%2Ces2016%2Ces2017%2Ces2018%2Ces2019"></script>
<!-- 或者按需加载 -->
<script>
if (!window.Promise) {
document.write('<script src="promise-polyfill.js"><\/script>');
}
</script>
特性检测模式:
javascript复制// 检测WebP支持
function canUseWebP() {
const elem = document.createElement('canvas');
return elem.toDataURL('image/webp').indexOf('data:image/webp') === 0;
}
// 检测触摸事件
const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints;
12. 项目实战:构建一个现代Web应用
12.1 技术选型与初始化
bash复制# 创建项目
npx create-react-app my-app --template typescript
cd my-app
# 添加必要依赖
npm install axios react-router-dom @reduxjs/toolkit
npm install -D eslint prettier husky lint-staged
# 配置Git钩子
npx husky install
echo "npx lint-staged" > .husky/pre-commit
12.2 核心模块实现
路由配置示例:
typescript复制// src/App.tsx
import { BrowserRouter, Routes, Route } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/products" element={<Products />} />
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
);
}
API服务层封装:
typescript复制// src/api/client.ts
import axios from 'axios';
const api = axios.create({
baseURL: process.env.REACT_APP_API_URL,
timeout: 10000,
});
// 请求拦截器
api.interceptors.request.use(config => {
const [token](https://taotoken.net?utm_source=general) = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// 响应拦截器
api.interceptors.response.use(
response => response.data,
error => {
if (error.response?.status === 401) {
window.location.href = '/login';
}
return Promise.reject(error);
}
);
export default api;
12.3 性能优化实战
代码分割与懒加载:
typescript复制// 动态导入组件
const ProductDetail = lazy(() => import('./ProductDetail'));
function App() {
return (
<Suspense fallback={<Spinner />}>
<ProductDetail />
</Suspense>
);
}
Webpack分包策略:
javascript复制// craco.config.js
module.exports = {
webpack: {
configure: {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
},
},
},
},
},
},
};
13. 前沿趋势与未来展望
13.1 Web Components标准化进展
javascript复制// 使用LitElement构建组件
import { LitElement, html, css } from 'lit';
class MyElement extends LitElement {
static styles = css`
:host { display: block; }
button { color: blue; }
`;
render() {
return html`<button @click=${this.handleClick}>Click</button>`;
}
handleClick() {
this.dispatchEvent(new CustomEvent('my-event'));
}
}
customElements.define('my-element', MyElement);
13.2 WebAssembly应用场景扩展
图像处理加速案例:
javascript复制// 使用Rust编写Wasm模块
// lib.rs
#[wasm_bindgen]
pub fn grayscale(input: &[u8]) -> Vec<u8> {
let mut output = input.to_vec();
for i in (0..output.len()).step_by(4) {
let r = output[i] as f32;
let g = output[i+1] as f32;
let b = output[i+2] as f32;
let gray = (0.299*r + 0.587*g + 0.114*b) as u8;
output[i] = gray;
output[i+1] = gray;
output[i+2] = gray;
}
output
}
// JavaScript调用
const wasm = await import('./pkg/image_processor.js');
const processed = wasm.grayscale(imageData);
13.3 服务端JavaScript演进
Node.js与Deno对比:
| 特性 | Node.js | Deno |
|---|---|---|
| 模块系统 | CommonJS/ESM | 纯ESM |
| 安全模型 | 完全权限 | 默认沙箱 |
| 内置工具 | 需要额外安装 | 内置(test/lint等) |
| TypeScript | 需要转译 | 原生支持 |
javascript复制// Deno示例:启动HTTP服务
import { serve } from "https://deno.land/std/http/server.ts";
serve((req) => new Response("Hello World"), { port: 8000 });
14. 开发者必备的软技能
14.1 高效调试思维训练
五步调试法:
- 复现问题:确定稳定复现步骤
- 定位范围:通过日志/断点缩小范围
- 假设验证:提出可能原因并验证
- 修复验证:实施修复并确认效果
- 预防措施:添加测试或监控
14.2 代码审查最佳实践
CR Checklist:
- [ ] 功能实现是否符合需求
- [ ] 是否存在安全漏洞
- [ ] 代码结构是否清晰
- [ ] 是否有性能隐患
- [ ] 测试覆盖是否充分
- [ ] 文档是否同步更新
14.3 技术决策框架
技术选型四象限:
- 开发效率:学习曲线、开发速度
- 运行性能:响应时间、吞吐量
- 维护成本:可调试性、文档质量
- 长期演进:社区活跃度、升级路径
javascript复制// 技术决策矩阵示例
const decisionMatrix = {
framework: {
React: { learning: 3, performance: 4, maintenance: 5 },
Vue: { learning: 5, performance: 4, maintenance: 4 },
Svelte: { learning: 4, performance: 5, maintenance: 3 }
}
};
15. 全栈技能拓展指南
15.1 Node.js后端开发基础
javascript复制// Express路由示例
const express = require('express');
const app = express();
app.get('/api/users', async (req, res) => {
try {
const users = await db.query('SELECT * FROM users');
res.json(users);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// 错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
15.2 数据库交互优化
SQL查询优化技巧:
sql复制-- 反例:全表扫描
SELECT * FROM users WHERE DATE(created_at) = '2023-01-01';
-- 正例:利用索引
SELECT * FROM users
WHERE created_at >= '2023-01-01'
AND created_at < '2023-01-02';
MongoDB性能优化:
javascript复制// 创建合适的索引
db.collection.createIndex({ username: 1 }, { unique: true });
// 查询优化:只返回必要字段
db.users.find({ status: 'active' }, { name: 1, email: 1 });
15.3 云原生部署实践
Docker容器化示例:
dockerfile复制# Dockerfile
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
Kubernetes部署配置:
yaml复制# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: my-registry/web-app:1.0.0
ports:
- containerPort: 3000
resources:
limits:
memory: "512Mi"
cpu: "500m"
16. 安全防护体系构建
16.1 常见Web攻击防御
XSS防护全方案:
html复制<!-- CSP策略 -->
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'">
<!-- HttpOnly Cookie -->
Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Strict
CSRF防护方案:
javascript复制// 生成并验证CSRF Token
app.use((req, res, next) => {
res.locals.csrfToken = req.csrfToken();
next();
});
// 表单中嵌入
<form action="/submit" method="POST">
<input type="hidden" name="_csrf" value="{{csrfToken}}">
</form>
16.2 认证授权最佳实践
JWT实现方案:
javascript复制// 生成Token
function generateToken(user) {
return jwt.sign(
{ userId: user.id },
process.env.JWT_SECRET,
{ expiresIn: '1h' }
);
}
// 验证中间件
function authenticate(req, res, next) {
const token = req.headers.authorization?.split(' ')[1];
if (!token) return res.sendStatus(401);
jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
}
16.3 敏感数据保护
前端加密方案:
javascript复制// 使用Web Crypto API加密
async function encryptData(data, password) {
const salt = crypto.getRandomValues(new Uint8Array(16));
const keyMaterial = await crypto.subtle.importKey(
'raw',
new TextEncoder().encode(password),
{ name: 'PBKDF2' },
false,
['deriveKey']
);
const key = await crypto.subtle.deriveKey(
{
name: 'PBKDF2',
salt,
iterations: 100000,
hash: 'SHA-256'
},
keyMaterial,
{ name: 'AES-GCM', length: 256 },
false,
['encrypt', 'decrypt']
);
const iv = crypto.getRandomValues(new Uint8Array(12));
const encrypted = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv },
key,
new TextEncoder().encode(data)
);
return { salt, iv, encrypted };
}
17. 监控与可观测性体系
17.1 前端监控方案
javascript复制// 错误监控
window.addEventListener('error', (event) => {
fetch('/api/log', {
method: 'POST',
body: JSON.stringify({
type: 'error',
message: event.message,
stack: event.error?.stack,
filename: event.filename,
lineno: event.lineno,
colno: event.colno
})
});
});
// 性能监控
const perfData = {
dns: performance.timing.domainLookupEnd - performance.timing.domainLookupStart,
tcp: performance.timing.connectEnd - performance.timing.connectStart,
ttfb: performance.timing.responseStart - performance.timing.requestStart
};
sendToAnalytics(perfData);
17.2 日志收集策略
结构化日志规范:
javascript复制// Winston日志配置
const logger = winston.createLogger({
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});
// 记录示例
logger.info('User login', {
userId: 123,
ip: '192.168.1.1',
user[Agent](https://taotoken.net?utm_source=general): req.headers['user-agent']
});
17.3 报警机制设计
健康检查与报警:
javascript复制// 健康检查端点
app.get('/health', (req, res) => {
const checks = {
database: checkDatabase(),
cache: checkCache(),
disk: checkDiskSpace()
};
const isHealthy = Object.values(checks).every(Boolean);
res.status(isHealthy ? 200 : 503).json(checks);
});
// 定时检查
setInterval(async () => {
const res = await fetch('http://localhost:3000/health');
if (!res.ok) {
sendAlert('Service Unhealthy', await res.json());
}
}, 60000);
18. 移动端专项优化
18.1 触摸事件处理
javascript复制// 手势识别实现
let startX, startY;
element.addEventListener('touchstart', (e) => {
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
});
element.addEventListener('touchmove', (e) => {
const diffX = e.touches[0].clientX - startX;
const diffY = e.touches[0].clientY - startY;
if (Math.abs(diffX) > Math.abs(diffY)) {
// 水平滑动
if (diffX > 0) console.log('右滑');
else console.log('左滑');
} else {
// 垂直滑动
if (diffY > 0) console.log('下滑');
else console.log('上滑');
}
}, { passive: true });
18.2 移动端性能调优
优化建议:
- 减少DOM节点数量(理想值<1000)
- 避免大型CSS选择器
- 使用will-change提示浏览器优化
- 优先使用transform/opacity动画
javascript复制// 使用IntersectionObserver懒加载
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
document.querySelectorAll('img.lazy').forEach(img => {
observer.observe(img);
});
18.3 PWA离线体验
javascript复制// Service Worker安装
self.addEventListener('install', (e) => {
e.waitUntil(
caches.open('v1').then((cache) => {
return cache.addAll([
'/',
'/index.html',
'/styles/main.css',
'/scripts/app.js'
]);
