JavaScript前端开发完整指南
1. JavaScript基础语法
变量声明和作用域
现代JavaScript提供了多种变量声明方式,每种都有其特定的用途。
// ES6+ 变量声明
const API_URL = 'https://api.example.com'; // 常量
let userCount = 0; // 块级作用域变量
var globalVar = 'legacy'; // 函数作用域(不推荐)
// 解构赋值
const user = { name: 'Alice', age: 25, city: 'Beijing' };
const { name, age } = user;
const numbers = [1, 2, 3, 4, 5];
const [first, second, ...rest] = numbers;
console.log(`用户 ${name} 今年 ${age} 岁`);
函数定义和箭头函数
// 传统函数声明
function calculateArea(width, height) {
return width * height;
}
// 函数表达式
const calculateVolume = function(length, width, height) {
return length * width * height;
};
// 箭头函数
const multiply = (a, b) => a * b;
// 复杂箭头函数
const processUserData = (users) => {
return users
.filter(user => user.active)
.map(user => ({
id: user.id,
name: user.name.toUpperCase(),
email: user.email.toLowerCase()
}))
.sort((a, b) => a.name.localeCompare(b.name));
};
// 高阶函数示例
const createMultiplier = (factor) => {
return (number) => number * factor;
};
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5)); // 10
console.log(triple(4)); // 12
2. 异步编程
Promise和async/await
// Promise 基础用法
function fetchUserData(userId) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (userId > 0) {
resolve({
id: userId,
name: `User ${userId}`,
email: `user${userId}@example.com`
});
} else {
reject(new Error('Invalid user ID'));
}
}, 1000);
});
}
// Promise 链式调用
fetchUserData(1)
.then(user => {
console.log('用户信息:', user);
return fetchUserPosts(user.id);
})
.then(posts => {
console.log('用户文章:', posts);
})
.catch(error => {
console.error('错误:', error.message);
});
// async/await 语法
async function getUserProfile(userId) {
try {
const user = await fetchUserData(userId);
const posts = await fetchUserPosts(user.id);
const comments = await fetchUserComments(user.id);
return {
user,
posts,
comments,
totalActivity: posts.length + comments.length
};
} catch (error) {
console.error('获取用户资料失败:', error);
throw error;
}
}
// 并发处理
async function fetchMultipleUsers(userIds) {
try {
const userPromises = userIds.map(id => fetchUserData(id));
const users = await Promise.all(userPromises);
console.log('所有用户:', users);
return users;
} catch (error) {
console.error('批量获取用户失败:', error);
}
}
Fetch API 和 HTTP 请求
// 现代 HTTP 请求处理
class ApiClient {
constructor(baseURL) {
this.baseURL = baseURL;
this.defaultHeaders = {
'Content-Type': 'application/json',
'Accept': 'application/json'
};
}
async request(endpoint, options = {}) {
const url = `${this.baseURL}${endpoint}`;
const config = {
headers: { ...this.defaultHeaders, ...options.headers },
...options
};
try {
const response = await fetch(url, config);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('application/json')) {
return await response.json();
}
return await response.text();
} catch (error) {
console.error('API请求失败:', error);
throw error;
}
}
// GET 请求
async get(endpoint, params = {}) {
const queryString = new URLSearchParams(params).toString();
const url = queryString ? `${endpoint}?${queryString}` : endpoint;
return this.request(url);
}
// POST 请求
async post(endpoint, data) {
return this.request(endpoint, {
method: 'POST',
body: JSON.stringify(data)
});
}
// PUT 请求
async put(endpoint, data) {
return this.request(endpoint, {
method: 'PUT',
body: JSON.stringify(data)
});
}
// DELETE 请求
async delete(endpoint) {
return this.request(endpoint, {
method: 'DELETE'
});
}
}
// 使用示例
const api = new ApiClient('https://jsonplaceholder.typicode.com');
async function demonstrateApiUsage() {
try {
// 获取所有用户
const users = await api.get('/users');
console.log('用户列表:', users);
// 创建新文章
const newPost = await api.post('/posts', {
title: '我的新文章',
body: '这是文章内容...',
userId: 1
});
console.log('新文章:', newPost);
// 更新文章
const updatedPost = await api.put(`/posts/${newPost.id}`, {
...newPost,
title: '更新后的文章标题'
});
console.log('更新后的文章:', updatedPost);
} catch (error) {
console.error('API操作失败:', error);
}
}
3. DOM 操作和事件处理
现代DOM操作
// DOM 查询和操作
class DOMHelper {
// 查询元素
static $(selector) {
return document.querySelector(selector);
}
static $$(selector) {
return Array.from(document.querySelectorAll(selector));
}
// 创建元素
static createElement(tag, attributes = {}, children = []) {
const element = document.createElement(tag);
// 设置属性
Object.entries(attributes).forEach(([key, value]) => {
if (key === 'className') {
element.className = value;
} else if (key === 'textContent') {
element.textContent = value;
} else if (key.startsWith('data-')) {
element.setAttribute(key, value);
} else {
element[key] = value;
}
});
// 添加子元素
children.forEach(child => {
if (typeof child === 'string') {
element.appendChild(document.createTextNode(child));
} else {
element.appendChild(child);
}
});
return element;
}
// 添加事件监听器
static addEventListeners(element, events) {
Object.entries(events).forEach(([event, handler]) => {
element.addEventListener(event, handler);
});
}
// 切换类名
static toggleClass(element, className, condition) {
if (condition === undefined) {
element.classList.toggle(className);
} else {
element.classList.toggle(className, condition);
}
}
}
// 实际应用示例:动态表格
class DataTable {
constructor(container, data) {
this.container = container;
this.data = data;
this.sortColumn = null;
this.sortDirection = 'asc';
this.render();
}
render() {
this.container.innerHTML = '';
// 创建表格
const table = DOMHelper.createElement('table', {
className: 'data-table'
});
// 创建表头
const thead = this.createHeader();
const tbody = this.createBody();
table.appendChild(thead);
table.appendChild(tbody);
this.container.appendChild(table);
}
createHeader() {
const thead = DOMHelper.createElement('thead');
const headerRow = DOMHelper.createElement('tr');
const columns = ['ID', '姓名', '邮箱', '城市', '操作'];
columns.forEach((column, index) => {
const th = DOMHelper.createElement('th', {
textContent: column,
'data-column': index
});
if (index < 4) { // 前4列可排序
th.style.cursor = 'pointer';
DOMHelper.addEventListeners(th, {
click: () => this.sortBy(index)
});
}
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
return thead;
}
createBody() {
const tbody = DOMHelper.createElement('tbody');
this.data.forEach((row, index) => {
const tr = DOMHelper.createElement('tr', {
className: index % 2 === 0 ? 'even' : 'odd'
});
// 数据列
[row.id, row.name, row.email, row.city].forEach(cellData => {
const td = DOMHelper.createElement('td', {
textContent: cellData
});
tr.appendChild(td);
});
// 操作列
const actionTd = DOMHelper.createElement('td');
const editBtn = DOMHelper.createElement('button', {
textContent: '编辑',
className: 'btn btn-primary'
});
const deleteBtn = DOMHelper.createElement('button', {
textContent: '删除',
className: 'btn btn-danger'
});
DOMHelper.addEventListeners(editBtn, {
click: () => this.editRow(index)
});
DOMHelper.addEventListeners(deleteBtn, {
click: () => this.deleteRow(index)
});
actionTd.appendChild(editBtn);
actionTd.appendChild(deleteBtn);
tr.appendChild(actionTd);
tbody.appendChild(tr);
});
return tbody;
}
sortBy(columnIndex) {
const columns = ['id', 'name', 'email', 'city'];
const column = columns[columnIndex];
if (this.sortColumn === column) {
this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';
} else {
this.sortColumn = column;
this.sortDirection = 'asc';
}
this.data.sort((a, b) => {
let aVal = a[column];
let bVal = b[column];
if (typeof aVal === 'string') {
aVal = aVal.toLowerCase();
bVal = bVal.toLowerCase();
}
if (this.sortDirection === 'asc') {
return aVal > bVal ? 1 : -1;
} else {
return aVal < bVal ? 1 : -1;
}
});
this.render();
}
editRow(index) {
const row = this.data[index];
const newName = prompt('请输入新姓名:', row.name);
if (newName) {
this.data[index].name = newName;
this.render();
}
}
deleteRow(index) {
if (confirm('确定要删除这行数据吗?')) {
this.data.splice(index, 1);
this.render();
}
}
}
// 使用示例
const sampleData = [
{ id: 1, name: '张三', email: 'zhangsan@example.com', city: '北京' },
{ id: 2, name: '李四', email: 'lisi@example.com', city: '上海' },
{ id: 3, name: '王五', email: 'wangwu@example.com', city: '广州' },
{ id: 4, name: '赵六', email: 'zhaoliu@example.com', city: '深圳' }
];
// 初始化表格
document.addEventListener('DOMContentLoaded', () => {
const container = DOMHelper.$('#table-container');
if (container) {
new DataTable(container, sampleData);
}
});
4. ES6+ 现代特性
模块化和类
// 现代JavaScript类定义
class EventEmitter {
constructor() {
this.events = new Map();
}
// 添加事件监听器
on(event, callback) {
if (!this.events.has(event)) {
this.events.set(event, []);
}
this.events.get(event).push(callback);
return this; // 支持链式调用
}
// 移除事件监听器
off(event, callback) {
if (!this.events.has(event)) return this;
const callbacks = this.events.get(event);
const index = callbacks.indexOf(callback);
if (index > -1) {
callbacks.splice(index, 1);
}
return this;
}
// 触发事件
emit(event, ...args) {
if (!this.events.has(event)) return this;
this.events.get(event).forEach(callback => {
try {
callback.apply(this, args);
} catch (error) {
console.error(`事件 ${event} 处理器出错:`, error);
}
});
return this;
}
// 一次性事件监听器
once(event, callback) {
const onceWrapper = (...args) => {
callback.apply(this, args);
this.off(event, onceWrapper);
};
return this.on(event, onceWrapper);
}
}
// 使用示例
const emitter = new EventEmitter();
emitter
.on('user:login', (user) => {
console.log(`用户 ${user.name} 已登录`);
})
.on('user:logout', (user) => {
console.log(`用户 ${user.name} 已登出`);
})
.once('app:ready', () => {
console.log('应用已准备就绪');
});
// 触发事件
emitter.emit('user:login', { name: '张三', id: 1 });
emitter.emit('app:ready');
装饰器和高级特性
// 工具函数和装饰器模式
const utils = {
// 防抖函数
debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func.apply(this, args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
},
// 节流函数
throttle(func, limit) {
let inThrottle;
return function executedFunction(...args) {
if (!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
},
// 深拷贝
deepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj;
if (obj instanceof Date) return new Date(obj.getTime());
if (obj instanceof Array) return obj.map(item => this.deepClone(item));
if (typeof obj === 'object') {
const clonedObj = {};
Object.keys(obj).forEach(key => {
clonedObj[key] = this.deepClone(obj[key]);
});
return clonedObj;
}
},
// 格式化数字
formatNumber(num, decimals = 2) {
return new Intl.NumberFormat('zh-CN', {
minimumFractionDigits: decimals,
maximumFractionDigits: decimals
}).format(num);
},
// 格式化日期
formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') {
const d = new Date(date);
const year = d.getFullYear();
const month = String(d.getMonth() + 1).padStart(2, '0');
const day = String(d.getDate()).padStart(2, '0');
const hours = String(d.getHours()).padStart(2, '0');
const minutes = String(d.getMinutes()).padStart(2, '0');
const seconds = String(d.getSeconds()).padStart(2, '0');
return format
.replace('YYYY', year)
.replace('MM', month)
.replace('DD', day)
.replace('HH', hours)
.replace('mm', minutes)
.replace('ss', seconds);
}
};
// 实际应用示例
const searchInput = document.querySelector('#search');
if (searchInput) {
const debouncedSearch = utils.debounce(async (query) => {
if (query.length < 2) return;
try {
const results = await api.get('/search', { q: query });
displaySearchResults(results);
} catch (error) {
console.error('搜索失败:', error);
}
}, 300);
searchInput.addEventListener('input', (e) => {
debouncedSearch(e.target.value);
});
}
总结
JavaScript是现代Web开发的核心技术,掌握以下要点:
- 现代语法: ES6+特性,箭头函数,解构赋值
- 异步编程: Promise, async/await, 错误处理
- DOM操作: 现代API,事件处理,性能优化
- 模块化: 类定义,事件系统,工具函数
- 最佳实践: 代码组织,错误处理,性能优化
继续学习React、Vue等框架,构建更复杂的应用!