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开发的核心技术,掌握以下要点:

  1. 现代语法: ES6+特性,箭头函数,解构赋值
  2. 异步编程: Promise, async/await, 错误处理
  3. DOM操作: 现代API,事件处理,性能优化
  4. 模块化: 类定义,事件系统,工具函数
  5. 最佳实践: 代码组织,错误处理,性能优化

继续学习React、Vue等框架,构建更复杂的应用!