⚡ JavaScript进阶学习

现代JavaScript(ES6+)带来了许多强大的新特性。通过学习这些进阶技术, 你将能够编写更加优雅、高效和可维护的JavaScript代码。

🎯
ES6+语法掌握
0%
🔄
异步编程能力
0%
📦
模块化开发
0%

📚 JavaScript版本发展历程

1995

JavaScript诞生

Brendan Eich在Netscape创造了JavaScript

2009

ES5发布

引入严格模式、JSON支持等特性

2015

ES6/ES2015

let/const、箭头函数、类、模块化

2024

ES2024

持续演进,每年发布新特性

🎯 ES6+ 现代语法

ES6+引入了许多新的语法特性,让JavaScript编程更加简洁和强大。

📝 变量声明:let、const vs var

特性 var let const
作用域 函数作用域 块级作用域 块级作用域
变量提升
重复声明 允许 不允许 不允许
重新赋值 允许 允许 不允许

🔧 交互式演示

scope-demo.js
function scopeTest() {
    if (true) {
        var varVariable = "我是var";
        let letVariable = "我是let";
        const constVariable = "我是const";
    }
    
    console.log(varVariable); // 可以访问
    try {
        console.log(letVariable); // 报错
    } catch (e) {
        console.log("let变量作用域错误:", e.message);
    }
    
    try {
        console.log(constVariable); // 报错
    } catch (e) {
        console.log("const变量作用域错误:", e.message);
    }
}

scopeTest();
控制台输出
点击"运行代码"查看结果
hoisting-demo.js
console.log("=== 变量提升演示 ===");

// var 变量提升
console.log("var变量:", varTest); // undefined (已提升但未赋值)
var varTest = "var已赋值";
console.log("var变量:", varTest); // "var已赋值"

// let 和 const 不会提升
try {
    console.log("let变量:", letTest); // 报错
} catch (e) {
    console.log("let访问错误:", e.message);
}

let letTest = "let已赋值";
console.log("let变量:", letTest);

// const 同样不会提升
try {
    console.log("const变量:", constTest); // 报错
} catch (e) {
    console.log("const访问错误:", e.message);
}

const constTest = "const已赋值";
console.log("const变量:", constTest);
控制台输出
点击"运行代码"查看结果
loop-demo.js
console.log("=== 循环中的var vs let ===");

// 使用var的问题
console.log("var版本:");
for (var i = 0; i < 3; i++) {
    setTimeout(() => {
        console.log("var i:", i); // 都打印3
    }, 100);
}

// 使用let的解决方案
console.log("let版本:");
for (let j = 0; j < 3; j++) {
    setTimeout(() => {
        console.log("let j:", j); // 打印0, 1, 2
    }, 200);
}

// 立即执行函数的var解决方案(ES6之前)
console.log("IIFE版本:");
for (var k = 0; k < 3; k++) {
    (function(index) {
        setTimeout(() => {
            console.log("IIFE k:", index); // 打印0, 1, 2
        }, 300);
    })(k);
}
控制台输出
点击"运行代码"查看结果

🏹 箭头函数

箭头函数提供了更简洁的函数语法,并且没有自己的this绑定。

传统函数

// 传统函数表达式
const multiply = function(a, b) {
    return a * b;
};

// 传统函数声明
function add(a, b) {
    return a + b;
}

箭头函数

// 箭头函数
const multiply = (a, b) => a * b;

// 单参数可省略括号
const square = x => x * x;

// 无参数需要空括号
const greet = () => "Hello World";

// 多行需要大括号和return
const complex = (a, b) => {
    const result = a * b;
    return result + 1;
};

🎯 this绑定差异演示

点击按钮查看演示结果

📦 解构赋值

解构赋值允许你从数组和对象中提取值,并赋值给变量。

🔢 数组解构

// 基础数组解构
const numbers = [1, 2, 3, 4, 5];
const [first, second, , fourth] = numbers;
// first = 1, second = 2, fourth = 4

// 默认值
const [a, b, c = 0] = [1, 2];
// a = 1, b = 2, c = 0

// 交换变量
let x = 1, y = 2;
[x, y] = [y, x];
// x = 2, y = 1

// 剩余参数
const [head, ...tail] = [1, 2, 3, 4];
// head = 1, tail = [2, 3, 4]

🏷️ 对象解构

// 基础对象解构
const person = { name: '张三', age: 25, city: '北京' };
const { name, age } = person;
// name = '张三', age = 25

// 重命名变量
const { name: personName, age: personAge } = person;
// personName = '张三', personAge = 25

// 默认值
const { name, age, country = '中国' } = person;
// country = '中国'

// 嵌套解构
const user = {
    id: 1,
    profile: {
        name: '李四',
        settings: { theme: 'dark' }
    }
};
const { profile: { name, settings: { theme } } } = user;
// name = '李四', theme = 'dark'

🔧 函数参数解构

// 函数参数解构
function greetUser({ name, age = 18 }) {
    return `你好 ${name},你今年 ${age} 岁`;
}

// 数组参数解构
function processCoordinates([x, y, z = 0]) {
    return { x, y, z };
}

// 混合解构
function createUser({ name, ...otherInfo }, [role, permission]) {
    return {
        name,
        role,
        permission,
        ...otherInfo
    };
}

🏋️ 解构练习

挑战:从以下数据中提取所需信息

const apiResponse = {
    status: 'success',
    data: {
        users: [
            { id: 1, name: '张三', email: 'zhangsan@example.com' },
            { id: 2, name: '李四', email: 'lisi@example.com' }
        ],
        pagination: { page: 1, total: 2 }
    }
};

任务:提取第一个用户的姓名和邮箱,以及总用户数

📝 模板字符串

模板字符串提供了更强大的字符串处理能力,支持多行字符串和表达式插值。

传统方式

// 字符串拼接
var name = '张三';
var age = 25;
var message = '你好,我是' + name + 
              ',今年' + age + '岁';

// 多行字符串
var html = '<div>' +
           '  <h1>标题</h1>' +
           '  <p>内容</p>' +
           '</div>';

模板字符串

// 表达式插值
const name = '张三';
const age = 25;
const message = `你好,我是${name},今年${age}岁`;

// 多行字符串
const html = `
<div>
  <h1>标题</h1>
  <p>内容</p>
</div>`;

// 表达式计算
const total = `总价:${price * quantity}元`;

🛠️ 模板字符串生成器

生成的模板字符串:
const message = `你好,我是${name},今年${age}岁,来自${city}`;
输出结果:
你好,我是张三,今年25岁,来自北京

🏷️ 标签模板函数

标签模板是模板字符串的高级形式,允许你用函数解析模板字符串。

// 高亮函数
function highlight(strings, ...values) {
    return strings.reduce((result, string, i) => {
        const value = values[i] ? `<mark>${values[i]}</mark>` : '';
        return result + string + value;
    }, '');
}

const name = '张三';
const score = 95;
const message = highlight`学生 ${name} 的成绩是 ${score} 分`;
// 输出:学生 <mark>张三</mark> 的成绩是 <mark>95</mark> 分

🔄 展开运算符和剩余参数

三个点(...)语法在不同上下文中有不同的作用。

📤 展开运算符 (Spread)

// 数组展开
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]

// 对象展开
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const merged = { ...obj1, ...obj2 }; // { a: 1, b: 2, c: 3, d: 4 }

// 函数调用
const numbers = [1, 2, 3, 4, 5];
const max = Math.max(...numbers); // 相当于 Math.max(1, 2, 3, 4, 5)

// 复制数组/对象
const originalArray = [1, 2, 3];
const copiedArray = [...originalArray]; // 浅拷贝

const originalObject = { name: '张三', age: 25 };
const copiedObject = { ...originalObject }; // 浅拷贝

📥 剩余参数 (Rest)

// 函数剩余参数
function sum(...numbers) {
    return numbers.reduce((total, num) => total + num, 0);
}

console.log(sum(1, 2, 3, 4)); // 10
console.log(sum(5, 10)); // 15

// 混合参数
function greet(greeting, ...names) {
    return `${greeting} ${names.join(', ')}!`;
}

console.log(greet('Hello', '张三', '李四', '王五'));
// "Hello 张三, 李四, 王五!"

// 数组解构中的剩余参数
const [first, second, ...others] = [1, 2, 3, 4, 5];
// first = 1, second = 2, others = [3, 4, 5]

// 对象解构中的剩余参数
const { name, age, ...otherInfo } = {
    name: '张三',
    age: 25,
    city: '北京',
    hobby: '编程'
};
// name = '张三', age = 25, otherInfo = { city: '北京', hobby: '编程' }

🎯 解构中的高级用法

// 数组的深度解构
const nestedArray = [[1, 2], [3, 4], [5, 6]];
const [[a, b], [c, d], ...rest] = nestedArray;
// a=1, b=2, c=3, d=4, rest=[[5, 6]]

// 对象的深度解构与重命名
const user = {
    name: '张三',
    profile: {
        age: 25,
        address: {
            city: '北京',
            district: '朝阳区'
        }
    },
    hobbies: ['编程', '阅读', '运动']
};

const {
    name: userName,
    profile: {
        age,
        address: { city, district }
    },
    hobbies: [firstHobby, ...otherHobbies]
} = user;

// 函数参数的复杂解构
function processOrder({
    orderId,
    customer: { name, email },
    items = [],
    shipping = { method: 'standard' },
    ...metadata
}) {
    return {
        id: orderId,
        customerName: name,
        customerEmail: email,
        itemCount: items.length,
        shippingMethod: shipping.method,
        additionalInfo: metadata
    };
}

🛠️ 实用工具函数

使用展开运算符和剩余参数创建实用的工具函数:

数组去重
const unique = (...arrays) => 
    [...new Set(arrays.flat())];
对象合并
const merge = (...objects) => 
    objects.reduce((acc, obj) => ({...acc, ...obj}), {});
数组分块
const chunk = (array, size) => 
    Array.from({length: Math.ceil(array.length / size)}, 
        (_, i) => array.slice(i * size, i * size + size));
深度克隆
const deepClone = (obj) => 
    JSON.parse(JSON.stringify(obj));

🏛️ ES6 类 (Classes)

ES6引入了class语法,提供了更清晰的面向对象编程方式。

🎯 基础类语法

// 定义一个基础类
class Person {
    // 构造函数
    constructor(name, age) {
        this.name = name;
        this.age = age;
        this._id = Math.random().toString(36).substr(2, 9); // 私有属性约定
    }
    
    // 实例方法
    introduce() {
        return `我是${this.name},今年${this.age}岁`;
    }
    
    // getter方法
    get id() {
        return this._id;
    }
    
    // setter方法
    set age(value) {
        if (value > 0 && value < 150) {
            this._age = value;
        } else {
            throw new Error('年龄必须在0-150之间');
        }
    }
    
    get age() {
        return this._age;
    }
    
    // 静态方法
    static compare(person1, person2) {
        return person1.age - person2.age;
    }
    
    // 静态属性
    static species = 'Homo sapiens';
}

// 使用类
const person1 = new Person('张三', 25);
const person2 = new Person('李四', 30);

console.log(person1.introduce()); // "我是张三,今年25岁"
console.log(Person.compare(person1, person2)); // -5
console.log(Person.species); // "Homo sapiens"

🧬 类的继承

// 父类
class Animal {
    constructor(name, species) {
        this.name = name;
        this.species = species;
    }
    
    makeSound() {
        return `${this.name}发出了声音`;
    }
    
    move() {
        return `${this.name}在移动`;
    }
}

// 子类继承父类
class Dog extends Animal {
    constructor(name, breed) {
        super(name, '犬类'); // 调用父类构造函数
        this.breed = breed;
    }
    
    // 重写父类方法
    makeSound() {
        return `${this.name}汪汪叫`;
    }
    
    // 子类特有方法
    wagTail() {
        return `${this.name}摇尾巴`;
    }
    
    // 调用父类方法
    introduce() {
        return `${super.makeSound()},它是一只${this.breed}`;
    }
}

class Cat extends Animal {
    constructor(name, color) {
        super(name, '猫科');
        this.color = color;
    }
    
    makeSound() {
        return `${this.name}喵喵叫`;
    }
    
    climb() {
        return `${this.color}色的${this.name}在爬树`;
    }
}

// 使用继承
const dog = new Dog('旺财', '金毛');
const cat = new Cat('咪咪', '橘');

console.log(dog.makeSound()); // "旺财汪汪叫"
console.log(dog.introduce()); // "旺财发出了声音,它是一只金毛"
console.log(cat.climb()); // "橘色的咪咪在爬树"

🚀 高级类特性

// 使用私有字段 (ES2022)
class BankAccount {
    #balance = 0; // 私有字段
    #accountNumber; // 私有字段
    
    constructor(initialBalance, accountNumber) {
        this.#balance = initialBalance;
        this.#accountNumber = accountNumber;
    }
    
    // 公共方法访问私有字段
    deposit(amount) {
        if (amount > 0) {
            this.#balance += amount;
            return `存入${amount}元,余额:${this.#balance}元`;
        }
        throw new Error('存款金额必须大于0');
    }
    
    withdraw(amount) {
        if (amount > 0 && amount <= this.#balance) {
            this.#balance -= amount;
            return `取出${amount}元,余额:${this.#balance}元`;
        }
        throw new Error('取款金额无效');
    }
    
    get balance() {
        return this.#balance;
    }
    
    // 私有方法
    #validateTransaction(amount) {
        return amount > 0 && amount <= this.#balance;
    }
    
    // 静态私有字段
    static #bankName = '学习银行';
    
    static getBankName() {
        return this.#bankName;
    }
}

// Mixin模式
const Flyable = {
    fly() {
        return `${this.name}在飞行`;
    }
};

const Swimmable = {
    swim() {
        return `${this.name}在游泳`;
    }
};

class Duck extends Animal {
    constructor(name) {
        super(name, '鸭类');
    }
}

// 添加混入功能
Object.assign(Duck.prototype, Flyable, Swimmable);

const duck = new Duck('唐老鸭');
console.log(duck.fly()); // "唐老鸭在飞行"
console.log(duck.swim()); // "唐老鸭在游泳"

🏋️ 类设计练习

任务:设计一个图书管理系统

  • 创建 Book 类,包含书名、作者、ISBN、价格等属性
  • 创建 Library 类,可以添加、删除、搜索图书
  • 创建 Member 类,表示图书馆会员
  • 实现借书、还书功能

🔄 异步编程

JavaScript是单线程语言,异步编程是处理耗时操作的重要技术。

📚 异步编程发展历程

1

回调函数 (Callbacks)

最早的异步解决方案,但容易产生"回调地狱"

getData(callback)
2

Promise (ES6)

解决回调地狱,提供链式调用

promise.then().catch()
3

async/await (ES2017)

让异步代码看起来像同步代码

await asyncFunction()

📞 回调函数 (Callbacks)

✅ 简单回调

// 基础回调函数
function fetchUserData(userId, callback) {
    setTimeout(() => {
        const userData = { id: userId, name: '张三', email: 'zhangsan@example.com' };
        callback(null, userData); // 错误优先的回调约定
    }, 1000);
}

// 使用回调
fetchUserData(123, (error, data) => {
    if (error) {
        console.error('获取用户数据失败:', error);
    } else {
        console.log('用户数据:', data);
    }
});

❌ 回调地狱

// 回调地狱示例
fetchUserData(123, (error, user) => {
    if (error) {
        console.error(error);
    } else {
        fetchUserPosts(user.id, (error, posts) => {
            if (error) {
                console.error(error);
            } else {
                fetchPostComments(posts[0].id, (error, comments) => {
                    if (error) {
                        console.error(error);
                    } else {
                        fetchCommentReplies(comments[0].id, (error, replies) => {
                            if (error) {
                                console.error(error);
                            } else {
                                console.log('最终数据:', replies);
                            }
                        });
                    }
                });
            }
        });
    }
});

🤝 Promise

Promise是异步编程的一种解决方案,代表了一个异步操作的最终完成或失败。

📊 Promise的三种状态

pending

初始状态,既没有被fulfilled,也没有被rejected

fulfilled

操作成功完成

rejected

操作失败

🚀 Promise基础用法

// 创建Promise
const myPromise = new Promise((resolve, reject) => {
    // 异步操作
    const success = Math.random() > 0.5;
    
    setTimeout(() => {
        if (success) {
            resolve('操作成功!'); // 成功时调用resolve
        } else {
            reject(new Error('操作失败!')); // 失败时调用reject
        }
    }, 1000);
});

// 使用Promise
myPromise
    .then(result => {
        console.log('成功:', result);
    })
    .catch(error => {
        console.error('失败:', error.message);
    });

// Promise快捷方法
const resolvedPromise = Promise.resolve('立即成功');
const rejectedPromise = Promise.reject(new Error('立即失败'));
// Promise链式调用
function fetchUser(id) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve({ id, name: '张三', departmentId: 1 });
        }, 500);
    });
}

function fetchDepartment(id) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve({ id, name: '技术部' });
        }, 300);
    });
}

function fetchProjects(departmentId) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve([
                { id: 1, name: '项目A' },
                { id: 2, name: '项目B' }
            ]);
        }, 400);
    });
}

// 链式调用解决回调地狱
fetchUser(123)
    .then(user => {
        console.log('用户信息:', user);
        return fetchDepartment(user.departmentId);
    })
    .then(department => {
        console.log('部门信息:', department);
        return fetchProjects(department.id);
    })
    .then(projects => {
        console.log('项目列表:', projects);
    })
    .catch(error => {
        console.error('链式调用出错:', error);
    });
// Promise.all - 等待所有Promise完成
const promise1 = Promise.resolve(3);
const promise2 = new Promise(resolve => setTimeout(() => resolve('foo'), 1000));
const promise3 = Promise.resolve(42);

Promise.all([promise1, promise2, promise3])
    .then(values => {
        console.log('Promise.all结果:', values); // [3, "foo", 42]
    });

// Promise.allSettled - 等待所有Promise结束(无论成功失败)
const promiseA = Promise.resolve('成功A');
const promiseB = Promise.reject('失败B');
const promiseC = Promise.resolve('成功C');

Promise.allSettled([promiseA, promiseB, promiseC])
    .then(results => {
        console.log('Promise.allSettled结果:', results);
        // [
        //   { status: 'fulfilled', value: '成功A' },
        //   { status: 'rejected', reason: '失败B' },
        //   { status: 'fulfilled', value: '成功C' }
        // ]
    });

// Promise.race - 返回最先完成的Promise
const fast = new Promise(resolve => setTimeout(() => resolve('快'), 100));
const slow = new Promise(resolve => setTimeout(() => resolve('慢'), 500));

Promise.race([fast, slow])
    .then(value => {
        console.log('Promise.race结果:', value); // "快"
    });

// Promise.any - 返回最先成功的Promise (ES2021)
const failFast = Promise.reject('快速失败');
const succeedSlow = new Promise(resolve => setTimeout(() => resolve('慢速成功'), 300));

Promise.any([failFast, succeedSlow])
    .then(value => {
        console.log('Promise.any结果:', value); // "慢速成功"
    })
    .catch(error => {
        console.log('所有Promise都失败了:', error);
    });
// Promise错误处理
function riskyOperation() {
    return new Promise((resolve, reject) => {
        const random = Math.random();
        setTimeout(() => {
            if (random > 0.7) {
                resolve('操作成功');
            } else if (random > 0.4) {
                reject(new Error('网络错误'));
            } else {
                throw new Error('未知错误'); // 同步错误也会被捕获
            }
        }, 500);
    });
}

// 错误处理方式1:使用catch
riskyOperation()
    .then(result => {
        console.log('成功:', result);
    })
    .catch(error => {
        console.error('捕获错误:', error.message);
    });

// 错误处理方式2:使用then的第二个参数
riskyOperation()
    .then(
        result => console.log('成功:', result),
        error => console.error('失败:', error.message)
    );

// 错误处理方式3:使用finally
riskyOperation()
    .then(result => console.log('成功:', result))
    .catch(error => console.error('失败:', error.message))
    .finally(() => console.log('操作完成')); // 无论成功失败都会执行

// 链式调用中的错误传播
Promise.resolve('开始')
    .then(value => {
        console.log('步骤1:', value);
        throw new Error('步骤1出错');
    })
    .then(value => {
        // 这里不会执行
        console.log('步骤2:', value);
        return '步骤2完成';
    })
    .catch(error => {
        console.error('捕获错误:', error.message);
        return '错误已处理'; // 返回值会传递给下一个then
    })
    .then(value => {
        console.log('恢复处理:', value); // 会执行
    });

🏋️ Promise实战练习

场景:模拟API调用

创建一个模拟的API调用函数,实现以下功能:

  • 模拟随机延迟(100-2000ms)
  • 70%成功率,30%失败率
  • 成功时返回用户数据
  • 失败时抛出网络错误

⚡ async/await

async/await是ES2017引入的语法糖,让异步代码看起来像同步代码。

Promise版本

function fetchUserData() {
    return fetchUser(123)
        .then(user => {
            console.log('用户:', user);
            return fetchPosts(user.id);
        })
        .then(posts => {
            console.log('文章:', posts);
            return fetchComments(posts[0].id);
        })
        .then(comments => {
            console.log('评论:', comments);
            return comments;
        })
        .catch(error => {
            console.error('错误:', error);
            throw error;
        });
}

async/await版本

async function fetchUserData() {
    try {
        const user = await fetchUser(123);
        console.log('用户:', user);
        
        const posts = await fetchPosts(user.id);
        console.log('文章:', posts);
        
        const comments = await fetchComments(posts[0].id);
        console.log('评论:', comments);
        
        return comments;
    } catch (error) {
        console.error('错误:', error);
        throw error;
    }
}

📝 async/await详细用法

// async函数总是返回Promise
async function basicExample() {
    // await只能在async函数中使用
    const result = await Promise.resolve('Hello');
    return result + ' World'; // 返回值会被包装成Promise
}

// 调用async函数
basicExample().then(result => {
    console.log(result); // "Hello World"
});

// 立即执行的async函数
(async () => {
    const data = await fetch('/api/data');
    console.log(await data.json());
})();

// async函数中的返回值
async function returnExample() {
    return 'direct return'; // 等同于 Promise.resolve('direct return')
}

async function throwExample() {
    throw new Error('async error'); // 等同于 Promise.reject(new Error('async error'))
}

// 等待非Promise值
async function awaitNonPromise() {
    const immediate = await 'immediate value'; // 立即返回
    const number = await 42; // 立即返回
    console.log(immediate, number);
}
// 串行执行(顺序等待)
async function serialExecution() {
    console.log('开始串行执行');
    const start = Date.now();
    
    const result1 = await delay(1000, 'task1');
    console.log('任务1完成:', result1);
    
    const result2 = await delay(1000, 'task2');
    console.log('任务2完成:', result2);
    
    const result3 = await delay(1000, 'task3');
    console.log('任务3完成:', result3);
    
    console.log('串行总时间:', Date.now() - start, 'ms'); // 约3000ms
}

// 并行执行(同时开始)
async function parallelExecution() {
    console.log('开始并行执行');
    const start = Date.now();
    
    // 同时启动所有任务
    const promise1 = delay(1000, 'task1');
    const promise2 = delay(1000, 'task2');
    const promise3 = delay(1000, 'task3');
    
    // 等待所有任务完成
    const results = await Promise.all([promise1, promise2, promise3]);
    console.log('所有任务完成:', results);
    
    console.log('并行总时间:', Date.now() - start, 'ms'); // 约1000ms
}

// 使用Promise.allSettled处理可能失败的并行任务
async function parallelWithErrorHandling() {
    const tasks = [
        delay(500, 'success1'),
        delay(800, 'success2'),
        Promise.reject(new Error('task3 failed')),
        delay(300, 'success4')
    ];
    
    const results = await Promise.allSettled(tasks);
    
    results.forEach((result, index) => {
        if (result.status === 'fulfilled') {
            console.log(`任务${index + 1}成功:`, result.value);
        } else {
            console.log(`任务${index + 1}失败:`, result.reason.message);
        }
    });
}

// 辅助函数
function delay(ms, value) {
    return new Promise(resolve => setTimeout(() => resolve(value), ms));
}
// try-catch错误处理
async function errorHandlingExample() {
    try {
        const result = await riskyAsyncOperation();
        console.log('操作成功:', result);
    } catch (error) {
        console.error('捕获错误:', error.message);
        // 可以在这里处理错误或重新抛出
    } finally {
        console.log('清理操作');
    }
}

// 多个await的错误处理
async function multipleAwaitError() {
    try {
        const user = await fetchUser(123);
        const posts = await fetchPosts(user.id); // 如果这里出错
        const comments = await fetchComments(posts[0].id); // 这里不会执行
        
        return { user, posts, comments };
    } catch (error) {
        console.error('流程中断:', error.message);
        // 决定如何处理错误
        return null;
    }
}

// 部分错误处理
async function partialErrorHandling() {
    let user, posts, comments;
    
    try {
        user = await fetchUser(123);
    } catch (error) {
        console.error('获取用户失败:', error.message);
        return null;
    }
    
    try {
        posts = await fetchPosts(user.id);
    } catch (error) {
        console.error('获取文章失败,使用默认值');
        posts = [];
    }
    
    try {
        comments = posts.length > 0 ? await fetchComments(posts[0].id) : [];
    } catch (error) {
        console.error('获取评论失败,使用默认值');
        comments = [];
    }
    
    return { user, posts, comments };
}

// 错误重试机制
async function withRetry(asyncFn, maxRetries = 3) {
    for (let i = 0; i < maxRetries; i++) {
        try {
            return await asyncFn();
        } catch (error) {
            console.log(`尝试 ${i + 1} 失败:`, error.message);
            if (i === maxRetries - 1) {
                throw error; // 最后一次重试失败,抛出错误
            }
            await delay(1000 * (i + 1)); // 延迟重试
        }
    }
}

function riskyAsyncOperation() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (Math.random() > 0.6) {
                resolve('操作成功');
            } else {
                reject(new Error('操作失败'));
            }
        }, 500);
    });
}
// 在循环中使用async/await
const urls = [
    '/api/users/1',
    '/api/users/2',
    '/api/users/3',
    '/api/users/4'
];

// 错误方式:forEach不等待async函数
async function wrongWay() {
    console.log('开始错误方式');
    urls.forEach(async (url) => {
        const data = await simulateAPICall(url);
        console.log('数据:', data);
    });
    console.log('错误方式结束'); // 这行会立即执行
}

// 正确方式1:使用for...of(串行)
async function serialLoop() {
    console.log('开始串行循环');
    for (const url of urls) {
        const data = await simulateAPICall(url);
        console.log('串行数据:', data);
    }
    console.log('串行循环结束');
}

// 正确方式2:使用Promise.all(并行)
async function parallelLoop() {
    console.log('开始并行循环');
    const promises = urls.map(url => simulateAPICall(url));
    const results = await Promise.all(promises);
    results.forEach((data, index) => {
        console.log(`并行数据${index + 1}:`, data);
    });
    console.log('并行循环结束');
}

// 正确方式3:使用传统for循环(串行)
async function traditionalLoop() {
    console.log('开始传统循环');
    for (let i = 0; i < urls.length; i++) {
        const data = await simulateAPICall(urls[i]);
        console.log(`传统循环数据${i + 1}:`, data);
    }
    console.log('传统循环结束');
}

// 限制并发数量
async function limitedConcurrency(urls, limit = 2) {
    const results = [];
    
    for (let i = 0; i < urls.length; i += limit) {
        const batch = urls.slice(i, i + limit);
        const batchPromises = batch.map(url => simulateAPICall(url));
        const batchResults = await Promise.all(batchPromises);
        results.push(...batchResults);
        console.log(`批次 ${Math.floor(i / limit) + 1} 完成`);
    }
    
    return results;
}

// reduce中使用async/await(串行处理)
async function reduceAsync() {
    const result = await urls.reduce(async (accPromise, url) => {
        const acc = await accPromise;
        const data = await simulateAPICall(url);
        return acc + data.length;
    }, Promise.resolve(0));
    
    console.log('reduce结果:', result);
    return result;
}

function simulateAPICall(url) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(`Data from ${url}`);
        }, Math.random() * 1000 + 200);
    });
}

🚀 实战项目:异步数据处理器

创建一个异步数据处理器,实现以下功能:

  • 从多个API获取数据
  • 处理失败重试机制
  • 实现数据缓存
  • 支持并发控制
  • 提供进度回调
// 完整的异步数据处理器实现会在这里显示

📦 ES6模块化

模块化是现代JavaScript开发的重要组成部分,让代码更加组织化和可维护。

📚 JavaScript模块化发展史

早期

全局变量

所有代码都在全局作用域,容易产生命名冲突

var myFunction = function() { };
2009

CommonJS (Node.js)

服务端模块化标准

const module = require('module');
2011

AMD (RequireJS)

异步模块定义,适用于浏览器

define(['dep'], function(dep) { });
2015

ES6 Modules

原生JavaScript模块标准

import { func } from 'module';

📝 ES6模块语法

📤 导出 (Export)

命名导出
// math.js
export const PI = 3.14159;

export function add(a, b) {
    return a + b;
}

export function multiply(a, b) {
    return a * b;
}

// 批量导出
const subtract = (a, b) => a - b;
const divide = (a, b) => a / b;

export { subtract, divide };

// 导出时重命名
export { subtract as minus, divide as div };
默认导出
// calculator.js
class Calculator {
    add(a, b) { return a + b; }
    subtract(a, b) { return a - b; }
}

export default Calculator;

// 或者直接导出
export default class {
    add(a, b) { return a + b; }
    subtract(a, b) { return a - b; }
}

// 导出函数
export default function calculate(operation, a, b) {
    switch(operation) {
        case 'add': return a + b;
        case 'subtract': return a - b;
        default: throw new Error('Unknown operation');
    }
}

// 导出值
export default 42;
混合导出
// utils.js
export const VERSION = '1.0.0';

export function formatDate(date) {
    return date.toLocaleDateString();
}

export class Logger {
    log(message) {
        console.log(`[${new Date()}] ${message}`);
    }
}

// 默认导出 + 命名导出
export default {
    name: 'UtilsLibrary',
    version: VERSION,
    formatDate,
    Logger
};

📥 导入 (Import)

命名导入
// 导入特定函数
import { add, multiply } from './math.js';

// 导入并重命名
import { subtract as minus, divide as div } from './math.js';

// 导入所有命名导出
import * as MathUtils from './math.js';
console.log(MathUtils.add(2, 3)); // 5
console.log(MathUtils.PI); // 3.14159

// 混合导入
import { PI, add } from './math.js';
默认导入
// 导入默认导出
import Calculator from './calculator.js';
const calc = new Calculator();

// 默认导入可以任意命名
import MyCalculator from './calculator.js';
import calc from './calculator.js';

// 导入默认导出的函数
import calculate from './calculator.js';
const result = calculate('add', 2, 3);
混合导入
// 同时导入默认和命名导出
import Utils, { VERSION, formatDate, Logger } from './utils.js';

// 动态导入
const mathModule = await import('./math.js');
const result = mathModule.add(2, 3);

// 条件导入
if (condition) {
    const { heavyFunction } = await import('./heavy-module.js');
    heavyFunction();
}

// 仅执行模块(副作用导入)
import './polyfill.js';
import './styles.css';

🛠️ 模块化实践

🏗️ 典型项目结构

📁 src/
📁 components/
📄 Button.js
📄 Modal.js
📄 index.js
📁 services/
📄 api.js
📄 auth.js
📄 storage.js
📁 utils/
📄 helpers.js
📄 constants.js
📄 validators.js
📄 main.js
components/index.js (桶文件)
// 统一导出所有组件
export { default as Button } from './Button.js';
export { default as Modal } from './Modal.js';

// 或者
import Button from './Button.js';
import Modal from './Modal.js';

export { Button, Modal };
services/api.js
// API服务模块
const BASE_URL = 'https://api.example.com';

class APIService {
    async get(endpoint) {
        const response = await fetch(`${BASE_URL}${endpoint}`);
        return response.json();
    }
    
    async post(endpoint, data) {
        const response = await fetch(`${BASE_URL}${endpoint}`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(data)
        });
        return response.json();
    }
}

export default new APIService();
main.js
// 应用入口文件
import { Button, Modal } from './components/index.js';
import APIService from './services/api.js';
import { formatDate, validate } from './utils/helpers.js';

class App {
    constructor() {
        this.initializeComponents();
        this.loadInitialData();
    }
    
    async initializeComponents() {
        // 初始化组件
    }
    
    async loadInitialData() {
        const data = await APIService.get('/users');
        console.log('用户数据:', data);
    }
}

export default App;

🎨 模块设计模式

单例模式
// logger.js - 单例模式
class Logger {
    constructor() {
        if (Logger.instance) {
            return Logger.instance;
        }
        
        this.logs = [];
        Logger.instance = this;
    }
    
    log(message) {
        const timestamp = new Date().toISOString();
        this.logs.push({ timestamp, message });
        console.log(`[${timestamp}] ${message}`);
    }
    
    getLogs() {
        return [...this.logs];
    }
}

export default new Logger(); // 导出实例,确保单例
工厂模式
// shape-factory.js
class Circle {
    constructor(radius) {
        this.radius = radius;
    }
    
    area() {
        return Math.PI * this.radius ** 2;
    }
}

class Rectangle {
    constructor(width, height) {
        this.width = width;
        this.height = height;
    }
    
    area() {
        return this.width * this.height;
    }
}

class ShapeFactory {
    static createShape(type, ...args) {
        switch (type) {
            case 'circle':
                return new Circle(...args);
            case 'rectangle':
                return new Rectangle(...args);
            default:
                throw new Error(`Unknown shape type: ${type}`);
        }
    }
}

export default ShapeFactory;
观察者模式
// event-emitter.js
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);
    }
    
    off(event, callback) {
        if (this.events.has(event)) {
            const callbacks = this.events.get(event);
            const index = callbacks.indexOf(callback);
            if (index > -1) {
                callbacks.splice(index, 1);
            }
        }
    }
    
    emit(event, ...args) {
        if (this.events.has(event)) {
            this.events.get(event).forEach(callback => {
                callback(...args);
            });
        }
    }
}

export default EventEmitter;
模块配置
// config.js
const config = {
    development: {
        apiUrl: 'http://localhost:3000/api',
        debug: true,
        logLevel: 'debug'
    },
    production: {
        apiUrl: 'https://api.production.com',
        debug: false,
        logLevel: 'error'
    }
};

const environment = process.env.NODE_ENV || 'development';

export default config[environment];

// 使用环境变量的配置
export const API_URL = process.env.API_URL || config[environment].apiUrl;
export const DEBUG = process.env.DEBUG === 'true' || config[environment].debug;

📦 模块打包和工具

Webpack配置示例
// webpack.config.js
const path = require('path');

module.exports = {
    entry: './src/main.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }
        ]
    },
    resolve: {
        alias: {
            '@': path.resolve(__dirname, 'src'),
            '@components': path.resolve(__dirname, 'src/components'),
            '@utils': path.resolve(__dirname, 'src/utils')
        }
    }
};
Vite配置示例
// vite.config.js
import { defineConfig } from 'vite';
import path from 'path';

export default defineConfig({
    resolve: {
        alias: {
            '@': path.resolve(__dirname, 'src'),
            '@components': path.resolve(__dirname, 'src/components')
        }
    },
    build: {
        rollupOptions: {
            output: {
                manualChunks: {
                    vendor: ['lodash', 'axios'],
                    components: ['./src/components/index.js']
                }
            }
        }
    }
});
Tree Shaking优化
// 良好的Tree Shaking写法
// utils.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export const multiply = (a, b) => a * b;

// main.js - 只导入需要的函数
import { add, multiply } from './utils.js';

// 避免的写法
// import * as utils from './utils.js'; // 会导入所有函数
// const result = utils.add(1, 2);

// package.json设置
{
    "sideEffects": false, // 标记为无副作用,可以安全地Tree Shake
    "sideEffects": ["*.css", "./src/polyfills.js"] // 指定有副作用的文件
}

⚡ 动态导入和懒加载

条件懒加载
// 根据条件动态加载模块
async function handleFeature() {
    if (userHasPermission) {
        const { AdminPanel } = await import('./AdminPanel.js');
        new AdminPanel().render();
    }
}

// 路由懒加载
const routes = {
    '/home': () => import('./pages/Home.js'),
    '/about': () => import('./pages/About.js'),
    '/contact': () => import('./pages/Contact.js')
};

async function navigateTo(path) {
    const pageModule = await routes[path]();
    const Page = pageModule.default;
    new Page().render();
}
组件懒加载
// 懒加载组件
class LazyComponent {
    constructor(selector, importFn) {
        this.selector = selector;
        this.importFn = importFn;
        this.loaded = false;
        this.setupIntersectionObserver();
    }
    
    setupIntersectionObserver() {
        const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting && !this.loaded) {
                    this.loadComponent();
                }
            });
        });
        
        const element = document.querySelector(this.selector);
        if (element) {
            observer.observe(element);
        }
    }
    
    async loadComponent() {
        try {
            this.loaded = true;
            const module = await this.importFn();
            const Component = module.default;
            new Component().render(this.selector);
        } catch (error) {
            console.error('组件加载失败:', error);
        }
    }
}

// 使用懒加载组件
new LazyComponent('.chart-container', () => import('./Chart.js'));
new LazyComponent('.map-container', () => import('./Map.js'));
模块预加载
// 模块预加载策略
class ModulePreloader {
    constructor() {
        this.preloadedModules = new Map();
    }
    
    // 预加载模块
    async preload(moduleMap) {
        const promises = Object.entries(moduleMap).map(async ([name, importFn]) => {
            try {
                const module = await importFn();
                this.preloadedModules.set(name, module);
                console.log(`模块 ${name} 预加载完成`);
            } catch (error) {
                console.error(`模块 ${name} 预加载失败:`, error);
            }
        });
        
        await Promise.allSettled(promises);
    }
    
    // 获取预加载的模块
    getModule(name) {
        return this.preloadedModules.get(name);
    }
    
    // 智能预加载(基于用户行为)
    intelligentPreload() {
        // 鼠标悬停预加载
        document.addEventListener('mouseover', (e) => {
            const link = e.target.closest('[data-preload]');
            if (link) {
                const moduleName = link.dataset.preload;
                this.preloadIfNotLoaded(moduleName);
            }
        });
        
        // 空闲时间预加载
        if ('requestIdleCallback' in window) {
            requestIdleCallback(() => {
                this.preloadNonCriticalModules();
            });
        }
    }
}

// 使用预加载器
const preloader = new ModulePreloader();
preloader.preload({
    chart: () => import('./Chart.js'),
    editor: () => import('./Editor.js'),
    dashboard: () => import('./Dashboard.js')
});

💡 模块化最佳实践

🎯

单一职责

  • 每个模块只做一件事
  • 保持模块的内聚性
  • 避免模块过于复杂
  • 明确模块的边界
🔗

依赖管理

  • 避免循环依赖
  • 使用依赖注入
  • 最小化外部依赖
  • 使用接口隔离
📝

命名约定

  • 使用描述性的模块名
  • 保持命名一致性
  • 避免缩写和简写
  • 使用语义化的导出名

性能优化

  • 合理使用动态导入
  • 实现代码分割
  • 避免不必要的导入
  • 利用Tree Shaking

🏋️ 综合练习:构建模块化应用

项目:创建一个模块化的任务管理应用

功能要求:

  • 任务的增删改查
  • 任务分类管理
  • 本地存储持久化
  • 用户偏好设置
  • 数据导入导出

技术要求:

  • 使用ES6模块化
  • 实现组件化设计
  • 使用观察者模式
  • 支持懒加载
  • 良好的错误处理

建议的项目结构:

src/
├── core/
│   ├── TaskManager.js     // 任务管理核心
│   ├── EventEmitter.js    // 事件系统
│   └── Storage.js         // 存储服务
├── components/
│   ├── TaskList.js        // 任务列表组件
│   ├── TaskForm.js        // 任务表单组件
│   ├── CategoryFilter.js  // 分类过滤组件
│   └── index.js           // 组件统一导出
├── services/
│   ├── api.js             // API服务
│   ├── import-export.js   // 导入导出功能
│   └── analytics.js       // 数据分析
├── utils/
│   ├── validators.js      // 数据验证
│   ├── formatters.js      // 数据格式化
│   └── constants.js       // 常量定义
└── main.js                // 应用入口

🚀 JavaScript高级技巧

掌握这些高级技巧,让你的JavaScript代码更加优雅和高效。

🧮 函数式编程

函数式编程强调使用纯函数和不可变数据,让代码更可预测和易于测试。

纯函数

✅ 纯函数
// 纯函数:相同输入总是产生相同输出,无副作用
function add(a, b) {
    return a + b;
}

function multiply(a, b) {
    return a * b;
}

// 高阶函数
function createMultiplier(factor) {
    return function(num) {
        return num * factor;
    };
}

const double = createMultiplier(2);
const triple = createMultiplier(3);
❌ 不纯函数
// 依赖外部状态
let counter = 0;
function impureIncrement() {
    return ++counter; // 副作用:修改外部变量
}

// 随机性
function impureRandom() {
    return Math.random(); // 相同输入产生不同输出
}

// 修改输入参数
function impureSort(array) {
    return array.sort(); // 副作用:修改原数组
}

函数组合

// 函数组合 - 将多个函数组合成一个函数
const compose = (...functions) => (value) =>
    functions.reduceRight((acc, fn) => fn(acc), value);

const pipe = (...functions) => (value) =>
    functions.reduce((acc, fn) => fn(acc), value);

// 示例函数
const addOne = x => x + 1;
const double = x => x * 2;
const square = x => x * x;

// 使用compose(从右到左)
const addOneDoubleSquare = compose(square, double, addOne);
console.log(addOneDoubleSquare(3)); // square(double(addOne(3))) = square(8) = 64

// 使用pipe(从左到右)
const addOneDoubleSquarePipe = pipe(addOne, double, square);
console.log(addOneDoubleSquarePipe(3)); // square(double(addOne(3))) = 64

柯里化 (Currying)

// 柯里化:将多参数函数转换为单参数函数序列
function curry(fn) {
    return function curried(...args) {
        if (args.length >= fn.length) {
            return fn.apply(this, args);
        } else {
            return function(...nextArgs) {
                return curried.apply(this, args.concat(nextArgs));
            };
        }
    };
}

// 原始函数
function add(a, b, c) {
    return a + b + c;
}

// 柯里化版本
const curriedAdd = curry(add);

// 多种调用方式
console.log(curriedAdd(1)(2)(3)); // 6
console.log(curriedAdd(1, 2)(3)); // 6
console.log(curriedAdd(1)(2, 3)); // 6
console.log(curriedAdd(1, 2, 3)); // 6

// 实用的柯里化示例
const multiply = curry((a, b) => a * b);
const double = multiply(2);
const triple = multiply(3);

const numbers = [1, 2, 3, 4, 5];
console.log(numbers.map(double)); // [2, 4, 6, 8, 10]
console.log(numbers.map(triple)); // [3, 6, 9, 12, 15]

函数式数组操作

// 函数式编程风格的数组操作
const users = [
    { name: '张三', age: 25, department: 'IT', salary: 8000 },
    { name: '李四', age: 30, department: 'HR', salary: 7000 },
    { name: '王五', age: 35, department: 'IT', salary: 12000 },
    { name: '赵六', age: 28, department: 'Finance', salary: 9000 }
];

// 函数式风格:链式操作
const result = users
    .filter(user => user.department === 'IT')    // 筛选IT部门
    .map(user => ({ ...user, bonus: user.salary * 0.1 }))  // 添加奖金
    .sort((a, b) => b.salary - a.salary)         // 按薪资降序
    .slice(0, 2);                                // 取前2名

console.log(result);

// 自定义函数式工具
const pipe = (...fns) => value => fns.reduce((acc, fn) => fn(acc), value);

const filterIT = users => users.filter(user => user.department === 'IT');
const addBonus = users => users.map(user => ({ ...user, bonus: user.salary * 0.1 }));
const sortBySalary = users => [...users].sort((a, b) => b.salary - a.salary);
const takeTwo = users => users.slice(0, 2);

const processUsers = pipe(filterIT, addBonus, sortBySalary, takeTwo);
const processedUsers = processUsers(users);

🏗️ 常用设计模式

设计模式是解决常见问题的可复用解决方案。

👁️ 观察者模式

定义对象间的一对多依赖关系,当对象状态改变时,所有依赖它的对象都会收到通知。

// 观察者模式实现
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} 收到通知:`, data);
    }
}

// 使用示例
const newsAgency = new Subject();

const tvStation = new Observer('电视台');
const newspaper = new Observer('报纸');
const website = new Observer('网站');

newsAgency.subscribe(tvStation);
newsAgency.subscribe(newspaper);
newsAgency.subscribe(website);

newsAgency.notify('重大新闻:JavaScript学习进度更新!');

// 实际应用:状态管理
class Store extends Subject {
    constructor() {
        super();
        this.state = {};
    }
    
    setState(newState) {
        this.state = { ...this.state, ...newState };
        this.notify(this.state);
    }
    
    getState() {
        return this.state;
    }
}

const store = new Store();
const component1 = new Observer('组件1');
const component2 = new Observer('组件2');

store.subscribe(component1);
store.subscribe(component2);
store.setState({ user: '张三', theme: 'dark' });

🎯 策略模式

定义一系列算法,把它们封装起来,并且使它们可以相互替换。

// 策略模式实现
class PaymentStrategy {
    pay(amount) {
        throw new Error('pay method must be implemented');
    }
}

class CreditCardPayment extends PaymentStrategy {
    constructor(cardNumber) {
        super();
        this.cardNumber = cardNumber;
    }
    
    pay(amount) {
        console.log(`使用信用卡 ${this.cardNumber} 支付 ${amount} 元`);
        return { success: true, method: 'credit_card', amount };
    }
}

class AlipayPayment extends PaymentStrategy {
    constructor(account) {
        super();
        this.account = account;
    }
    
    pay(amount) {
        console.log(`使用支付宝账户 ${this.account} 支付 ${amount} 元`);
        return { success: true, method: 'alipay', amount };
    }
}

class WeChatPayment extends PaymentStrategy {
    constructor(phoneNumber) {
        super();
        this.phoneNumber = phoneNumber;
    }
    
    pay(amount) {
        console.log(`使用微信账户 ${this.phoneNumber} 支付 ${amount} 元`);
        return { success: true, method: 'wechat', amount };
    }
}

// 支付上下文
class PaymentContext {
    constructor(strategy) {
        this.strategy = strategy;
    }
    
    setStrategy(strategy) {
        this.strategy = strategy;
    }
    
    executePayment(amount) {
        return this.strategy.pay(amount);
    }
}

// 使用示例
const payment = new PaymentContext(new CreditCardPayment('1234-5678-9012-3456'));
payment.executePayment(100);

// 切换策略
payment.setStrategy(new AlipayPayment('13800138000'));
payment.executePayment(200);

// 函数式策略模式
const paymentStrategies = {
    creditCard: (cardNumber) => (amount) => ({
        success: true,
        method: 'credit_card',
        message: `信用卡 ${cardNumber} 支付 ${amount} 元成功`
    }),
    
    alipay: (account) => (amount) => ({
        success: true,
        method: 'alipay',
        message: `支付宝 ${account} 支付 ${amount} 元成功`
    }),
    
    wechat: (phone) => (amount) => ({
        success: true,
        method: 'wechat',
        message: `微信 ${phone} 支付 ${amount} 元成功`
    })
};

const processPayment = (strategy, config, amount) => {
    return paymentStrategies[strategy](config)(amount);
};

🎨 装饰器模式

动态地给对象添加新功能,而不改变其结构。

// 装饰器模式实现
class Coffee {
    cost() {
        return 10;
    }
    
    description() {
        return '咖啡';
    }
}

// 装饰器基类
class CoffeeDecorator {
    constructor(coffee) {
        this.coffee = coffee;
    }
    
    cost() {
        return this.coffee.cost();
    }
    
    description() {
        return this.coffee.description();
    }
}

// 具体装饰器
class MilkDecorator extends CoffeeDecorator {
    cost() {
        return this.coffee.cost() + 2;
    }
    
    description() {
        return this.coffee.description() + ' + 牛奶';
    }
}

class SugarDecorator extends CoffeeDecorator {
    cost() {
        return this.coffee.cost() + 1;
    }
    
    description() {
        return this.coffee.description() + ' + 糖';
    }
}

class VanillaDecorator extends CoffeeDecorator {
    cost() {
        return this.coffee.cost() + 3;
    }
    
    description() {
        return this.coffee.description() + ' + 香草';
    }
}

// 使用装饰器
let myCoffee = new Coffee();
console.log(`${myCoffee.description()}: ${myCoffee.cost()}元`);

myCoffee = new MilkDecorator(myCoffee);
console.log(`${myCoffee.description()}: ${myCoffee.cost()}元`);

myCoffee = new SugarDecorator(myCoffee);
console.log(`${myCoffee.description()}: ${myCoffee.cost()}元`);

myCoffee = new VanillaDecorator(myCoffee);
console.log(`${myCoffee.description()}: ${myCoffee.cost()}元`);

// 函数式装饰器
const withLogging = (fn) => {
    return function(...args) {
        console.log(`调用函数 ${fn.name},参数:`, args);
        const result = fn.apply(this, args);
        console.log(`函数 ${fn.name} 返回:`, result);
        return result;
    };
};

const withTiming = (fn) => {
    return function(...args) {
        const start = performance.now();
        const result = fn.apply(this, args);
        const end = performance.now();
        console.log(`函数 ${fn.name} 执行时间: ${end - start}ms`);
        return result;
    };
};

// 使用函数装饰器
function calculate(a, b) {
    return a * b + Math.random();
}

const decoratedCalculate = withTiming(withLogging(calculate));
decoratedCalculate(5, 10);

🔄 代理模式

为其他对象提供一种代理以控制对这个对象的访问。

// 使用ES6 Proxy实现代理模式
class DatabaseService {
    constructor() {
        this.data = {
            users: [
                { id: 1, name: '张三', email: 'zhangsan@example.com' },
                { id: 2, name: '李四', email: 'lisi@example.com' }
            ]
        };
    }
    
    getUser(id) {
        console.log(`从数据库获取用户 ${id}`);
        return this.data.users.find(user => user.id === id);
    }
    
    getAllUsers() {
        console.log('从数据库获取所有用户');
        return this.data.users;
    }
}

// 缓存代理
class CachedDatabaseService {
    constructor(databaseService) {
        this.databaseService = databaseService;
        this.cache = new Map();
        
        return new Proxy(this, {
            get(target, prop) {
                if (prop === 'getUser') {
                    return function(id) {
                        const cacheKey = `user_${id}`;
                        if (target.cache.has(cacheKey)) {
                            console.log(`从缓存获取用户 ${id}`);
                            return target.cache.get(cacheKey);
                        }
                        
                        const user = target.databaseService.getUser(id);
                        target.cache.set(cacheKey, user);
                        return user;
                    };
                }
                
                if (prop === 'getAllUsers') {
                    return function() {
                        const cacheKey = 'all_users';
                        if (target.cache.has(cacheKey)) {
                            console.log('从缓存获取所有用户');
                            return target.cache.get(cacheKey);
                        }
                        
                        const users = target.databaseService.getAllUsers();
                        target.cache.set(cacheKey, users);
                        return users;
                    };
                }
                
                return target[prop];
            }
        });
    }
}

// 权限代理
const createSecureProxy = (target, permissions) => {
    return new Proxy(target, {
        get(obj, prop) {
            if (!permissions.includes(prop)) {
                throw new Error(`没有权限访问 ${prop}`);
            }
            return obj[prop];
        },
        
        set(obj, prop, value) {
            if (!permissions.includes(`set_${prop}`)) {
                throw new Error(`没有权限设置 ${prop}`);
            }
            obj[prop] = value;
            return true;
        }
    });
};

// 验证代理
const createValidationProxy = (target, validators) => {
    return new Proxy(target, {
        set(obj, prop, value) {
            if (validators[prop] && !validators[prop](value)) {
                throw new Error(`${prop} 的值 ${value} 不合法`);
            }
            obj[prop] = value;
            return true;
        }
    });
};

// 使用示例
const db = new DatabaseService();
const cachedDb = new CachedDatabaseService(db);

// 第一次调用,从数据库获取
cachedDb.getUser(1);
// 第二次调用,从缓存获取
cachedDb.getUser(1);

// 权限控制示例
const sensitiveData = { secret: 'top-secret', public: 'everyone-can-see' };
const secureData = createSecureProxy(sensitiveData, ['public']);

try {
    console.log(secureData.public); // 正常访问
    console.log(secureData.secret); // 抛出错误
} catch (error) {
    console.error(error.message);
}

// 数据验证示例
const user = {};
const validatedUser = createValidationProxy(user, {
    email: value => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
    age: value => typeof value === 'number' && value > 0 && value < 150
});

try {
    validatedUser.email = 'test@example.com'; // 正常
    validatedUser.age = 25; // 正常
    validatedUser.age = -5; // 抛出错误
} catch (error) {
    console.error(error.message);
}

⚡ 性能优化技巧

了解这些性能优化技巧,让你的JavaScript代码运行更快。

🎯 防抖和节流

// 防抖:延迟执行,如果在延迟时间内再次触发,则重新计时
function debounce(func, wait) {
    let timeout;
    return function executedFunction(...args) {
        const later = () => {
            clearTimeout(timeout);
            func(...args);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
    };
}

// 节流:固定时间间隔内只执行一次
function throttle(func, limit) {
    let inThrottle;
    return function(...args) {
        if (!inThrottle) {
            func.apply(this, args);
            inThrottle = true;
            setTimeout(() => inThrottle = false, limit);
        }
    };
}

// 使用示例
const expensiveOperation = () => {
    console.log('执行昂贵操作');
    // 模拟昂贵操作
    for (let i = 0; i < 1000000; i++) {
        Math.random();
    }
};

const debouncedOperation = debounce(expensiveOperation, 300);
const throttledOperation = throttle(expensiveOperation, 300);

// 搜索框防抖
const searchInput = document.querySelector('#search');
const debouncedSearch = debounce((query) => {
    console.log('搜索:', query);
    // 发送搜索请求
}, 300);

searchInput?.addEventListener('input', (e) => {
    debouncedSearch(e.target.value);
});

// 滚动事件节流
const throttledScroll = throttle(() => {
    console.log('滚动事件处理');
    // 处理滚动逻辑
}, 100);

window.addEventListener('scroll', throttledScroll);

💾 缓存策略

// 记忆化缓存
const memoize = (fn) => {
    const cache = new Map();
    return function(...args) {
        const key = JSON.stringify(args);
        if (cache.has(key)) {
            console.log('从缓存返回结果');
            return cache.get(key);
        }
        const result = fn.apply(this, args);
        cache.set(key, result);
        return result;
    };
};

// 斐波那契数列(带缓存)
const fibonacci = memoize((n) => {
    console.log(`计算 fibonacci(${n})`);
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
});

// LRU缓存实现
class LRUCache {
    constructor(capacity) {
        this.capacity = capacity;
        this.cache = new Map();
    }
    
    get(key) {
        if (this.cache.has(key)) {
            // 移动到最新位置
            const value = this.cache.get(key);
            this.cache.delete(key);
            this.cache.set(key, value);
            return value;
        }
        return -1;
    }
    
    set(key, value) {
        if (this.cache.has(key)) {
            this.cache.delete(key);
        } else if (this.cache.size >= this.capacity) {
            // 删除最久未使用的项
            const firstKey = this.cache.keys().next().value;
            this.cache.delete(firstKey);
        }
        this.cache.set(key, value);
    }
}

// HTTP请求缓存
class HTTPCache {
    constructor(ttl = 5 * 60 * 1000) { // 默认5分钟过期
        this.cache = new Map();
        this.ttl = ttl;
    }
    
    async fetch(url, options = {}, useCache = true) {
        const cacheKey = `${url}_${JSON.stringify(options)}`;
        
        if (useCache && this.cache.has(cacheKey)) {
            const cached = this.cache.get(cacheKey);
            if (Date.now() - cached.timestamp < this.ttl) {
                console.log('使用缓存数据');
                return cached.data;
            } else {
                this.cache.delete(cacheKey);
            }
        }
        
        console.log('发送HTTP请求');
        const response = await fetch(url, options);
        const data = await response.json();
        
        if (useCache) {
            this.cache.set(cacheKey, {
                data,
                timestamp: Date.now()
            });
        }
        
        return data;
    }
}

const httpCache = new HTTPCache();
// httpCache.fetch('/api/users');

🔄 虚拟滚动

// 虚拟滚动实现(适用于大数据列表)
class VirtualScroll {
    constructor(container, items, itemHeight, visibleCount) {
        this.container = container;
        this.items = items;
        this.itemHeight = itemHeight;
        this.visibleCount = visibleCount;
        this.startIndex = 0;
        this.endIndex = visibleCount;
        
        this.setupContainer();
        this.render();
        this.bindEvents();
    }
    
    setupContainer() {
        this.container.style.overflow = 'auto';
        this.container.style.height = `${this.visibleCount * this.itemHeight}px`;
        
        // 创建滚动容器
        this.scrollContainer = document.createElement('div');
        this.scrollContainer.style.height = `${this.items.length * this.itemHeight}px`;
        this.scrollContainer.style.position = 'relative';
        
        // 创建可见项容器
        this.visibleContainer = document.createElement('div');
        this.visibleContainer.style.position = 'absolute';
        this.visibleContainer.style.width = '100%';
        
        this.scrollContainer.appendChild(this.visibleContainer);
        this.container.appendChild(this.scrollContainer);
    }
    
    render() {
        // 清空容器
        this.visibleContainer.innerHTML = '';
        
        // 只渲染可见项
        for (let i = this.startIndex; i < this.endIndex && i < this.items.length; i++) {
            const item = document.createElement('div');
            item.style.height = `${this.itemHeight}px`;
            item.style.position = 'absolute';
            item.style.top = `${i * this.itemHeight}px`;
            item.style.width = '100%';
            item.textContent = this.items[i];
            item.style.borderBottom = '1px solid #eee';
            item.style.display = 'flex';
            item.style.alignItems = 'center';
            item.style.padding = '0 10px';
            
            this.visibleContainer.appendChild(item);
        }
        
        console.log(`渲染项目 ${this.startIndex} 到 ${this.endIndex - 1}`);
    }
    
    bindEvents() {
        this.container.addEventListener('scroll', () => {
            const scrollTop = this.container.scrollTop;
            const newStartIndex = Math.floor(scrollTop / this.itemHeight);
            const newEndIndex = Math.min(
                newStartIndex + this.visibleCount + 1,
                this.items.length
            );
            
            if (newStartIndex !== this.startIndex || newEndIndex !== this.endIndex) {
                this.startIndex = newStartIndex;
                this.endIndex = newEndIndex;
                this.render();
            }
        });
    }
}

// 生成大量测试数据
const generateLargeDataset = (count) => {
    return Array.from({ length: count }, (_, i) => `列表项 ${i + 1}`);
};

// 使用虚拟滚动
const largeDataset = generateLargeDataset(10000);
// const virtualList = new VirtualScroll(
//     document.getElementById('virtual-list'),
//     largeDataset,
//     50,  // 每项高度
//     20   // 可见项数量
// );

🎭 Web Workers

// Web Workers用于CPU密集型任务
class WorkerPool {
    constructor(workerScript, poolSize = 4) {
        this.workerScript = workerScript;
        this.poolSize = poolSize;
        this.workers = [];
        this.taskQueue = [];
        this.busyWorkers = new Set();
        
        this.initWorkers();
    }
    
    initWorkers() {
        for (let i = 0; i < this.poolSize; i++) {
            const worker = new Worker(this.workerScript);
            worker.id = i;
            
            worker.onmessage = (e) => {
                this.handleWorkerMessage(worker, e);
            };
            
            worker.onerror = (error) => {
                console.error(`Worker ${worker.id} 错误:`, error);
            };
            
            this.workers.push(worker);
        }
    }
    
    handleWorkerMessage(worker, e) {
        const { taskId, result, error } = e.data;
        
        // 从忙碌列表中移除
        this.busyWorkers.delete(worker);
        
        // 查找对应的任务回调
        const taskIndex = this.taskQueue.findIndex(task => task.id === taskId);
        if (taskIndex !== -1) {
            const task = this.taskQueue.splice(taskIndex, 1)[0];
            
            if (error) {
                task.reject(new Error(error));
            } else {
                task.resolve(result);
            }
        }
        
        // 处理队列中的下一个任务
        this.processNextTask();
    }
    
    execute(data) {
        return new Promise((resolve, reject) => {
            const taskId = Date.now() + Math.random();
            const task = { id: taskId, data, resolve, reject };
            
            // 寻找空闲worker
            const availableWorker = this.workers.find(worker => 
                !this.busyWorkers.has(worker)
            );
            
            if (availableWorker) {
                this.assignTask(availableWorker, task);
            } else {
                // 添加到队列
                this.taskQueue.push(task);
            }
        });
    }
    
    assignTask(worker, task) {
        this.busyWorkers.add(worker);
        worker.postMessage({
            taskId: task.id,
            data: task.data
        });
    }
    
    processNextTask() {
        if (this.taskQueue.length > 0) {
            const availableWorker = this.workers.find(worker => 
                !this.busyWorkers.has(worker)
            );
            
            if (availableWorker) {
                const task = this.taskQueue.shift();
                this.assignTask(availableWorker, task);
            }
        }
    }
    
    terminate() {
        this.workers.forEach(worker => worker.terminate());
        this.workers = [];
        this.taskQueue = [];
        this.busyWorkers.clear();
    }
}

// Worker脚本内容(通常是单独的文件)
const workerScriptContent = `
self.onmessage = function(e) {
    const { taskId, data } = e.data;
    
    try {
        // 执行CPU密集型任务
        const result = performHeavyCalculation(data);
        
        self.postMessage({
            taskId,
            result
        });
    } catch (error) {
        self.postMessage({
            taskId,
            error: error.message
        });
    }
};

function performHeavyCalculation(data) {
    // 模拟复杂计算
    const { start, end } = data;
    let sum = 0;
    
    for (let i = start; i <= end; i++) {
        sum += Math.sqrt(i) * Math.sin(i);
    }
    
    return sum;
}
`;

// 创建Blob URL作为Worker脚本
const createWorkerFromScript = (scriptContent) => {
    const blob = new Blob([scriptContent], { type: 'application/javascript' });
    return URL.createObjectURL(blob);
};

// 使用Worker Pool
async function demonstrateWorkerPool() {
    const workerUrl = createWorkerFromScript(workerScriptContent);
    const workerPool = new WorkerPool(workerUrl, 2);
    
    const tasks = [
        { start: 1, end: 100000 },
        { start: 100001, end: 200000 },
        { start: 200001, end: 300000 },
        { start: 300001, end: 400000 }
    ];
    
    console.log('开始并行计算...');
    const startTime = performance.now();
    
    try {
        const results = await Promise.all(
            tasks.map(task => workerPool.execute(task))
        );
        
        const endTime = performance.now();
        console.log('计算结果:', results);
        console.log(`总耗时: ${endTime - startTime}ms`);
    } catch (error) {
        console.error('计算失败:', error);
    } finally {
        workerPool.terminate();
        URL.revokeObjectURL(workerUrl);
    }
}

🎓 综合实战项目

项目:高性能数据可视化仪表板

运用所学的所有JavaScript进阶技术,构建一个完整的数据可视化应用。

🎯 核心功能
  • 实时数据获取和显示
  • 大数据集的虚拟滚动
  • 交互式图表组件
  • 数据筛选和搜索
  • 用户偏好设置
⚡ 技术要求
  • ES6+模块化架构
  • async/await异步处理
  • 设计模式应用
  • 性能优化技巧
  • 错误处理机制
🎨 用户体验
  • 响应式设计
  • 流畅的动画效果
  • 友好的加载状态
  • 直观的操作界面
  • 无障碍功能支持

🛠️ 项目实现空间

📐 架构设计
🔧 核心模块
🧩 组件库
🌐 服务层
🚀 应用入口
📱 项目预览
点击"运行项目"查看效果

📊 项目评估

代码质量
0/100
功能完整性
0/100
性能优化
0/100
用户体验
0/100

🎯 JavaScript进阶学习总结

🏆 你已经掌握的技能

🎯

ES6+现代语法

  • let/const变量声明
  • 箭头函数和this绑定
  • 解构赋值和展开运算符
  • 模板字符串和标签模板
  • ES6类和继承机制
🔄

异步编程大师

  • Promise原理和应用
  • async/await语法糖
  • 并行和串行处理
  • 错误处理和重试机制
  • 异步循环和高级用法
📦

模块化开发专家

  • ES6模块导入导出
  • 项目架构设计
  • 代码分割和懒加载
  • 模块打包和优化
  • 设计模式应用

性能优化高手

  • 防抖节流技术
  • 缓存策略实现
  • 虚拟滚动技术
  • Web Workers应用
  • 函数式编程思维

🚀 下一步学习建议

1

前端框架深入

学习React、Vue或Angular等现代前端框架

React Hooks Vue Composition API 状态管理
2

构建工具和工程化

掌握现代前端工程化工具和流程

Webpack Vite CI/CD
3

TypeScript强类型

学习TypeScript提升代码质量和开发效率

类型系统 接口定义 泛型编程
4

全栈开发

学习Node.js和数据库,成为全栈开发者

Node.js Express 数据库

💪 最终挑战

🏗️ 构建个人项目作品集

难度:
⭐⭐⭐⭐⭐

运用所学的所有JavaScript进阶技术,从零开始构建一个完整的项目作品集网站:

功能要求:
  • 响应式项目展示页面
  • 交互式技能雷达图
  • 动态简历生成器
  • 博客文章管理系统
  • 实时聊天功能
技术要求:
  • 使用ES6+模块化开发
  • 实现PWA离线功能
  • 集成第三方API服务
  • 优化性能和SEO
  • 部署到云服务平台

建议完成时间:2-4周

评估标准:代码质量、功能完整性、用户体验、创新性

🎓 JavaScript进阶毕业证书

JavaScript进阶开发者认证

恭喜您完成了JavaScript进阶课程学习

ES6+语法异步编程模块化开发性能优化
颁发日期:2024年1月