错误类型和异常处理

JavaScript中的错误类型

// JavaScript中的内置错误类型

// 1. Error - 通用错误类型
try {
  throw new Error('这是一个通用错误');
} catch (error) {
  console.log('错误类型:', error.constructor.name); // "Error"
  console.log('错误消息:', error.message);
  console.log('错误堆栈:', error.stack);
}

// 2. SyntaxError - 语法错误
try {
  eval('var a = ;'); // 语法错误
} catch (error) {
  console.log('语法错误:', error.message);
}

// 3. ReferenceError - 引用错误
try {
  console.log(undefinedVariable); // 引用未定义的变量
} catch (error) {
  console.log('引用错误:', error.message);
}

// 4. TypeError - 类型错误
try {
  null.someMethod(); // 在null上调用方法
} catch (error) {
  console.log('类型错误:', error.message);
}

// 5. RangeError - 范围错误
try {
  const arr = new Array(-1); // 负数长度
} catch (error) {
  console.log('范围错误:', error.message);
}

// 6. URIError - URI错误
try {
  decodeURIComponent('%'); // 无效的URI组件
} catch (error) {
  console.log('URI错误:', error.message);
}

// 7. EvalError - eval错误(很少使用)
// 现代JavaScript中很少遇到

// 错误对象的属性
function demonstrateErrorProperties() {
  try {
    throw new Error('演示错误属性');
  } catch (error) {
    console.log('错误属性演示:');
    console.log('name:', error.name);           // 错误名称
    console.log('message:', error.message);     // 错误消息
    console.log('stack:', error.stack);         // 堆栈跟踪
    console.log('fileName:', error.fileName);   // 文件名(某些浏览器)
    console.log('lineNumber:', error.lineNumber); // 行号(某些浏览器)
    console.log('columnNumber:', error.columnNumber); // 列号(某些浏览器)
  }
}

demonstrateErrorProperties();

// 检查错误类型
function handleDifferentErrors() {
  const errors = [
    new Error('通用错误'),
    new TypeError('类型错误'),
    new ReferenceError('引用错误'),
    new RangeError('范围错误')
  ];
  
  errors.forEach(error => {
    try {
      throw error;
    } catch (e) {
      if (e instanceof TypeError) {
        console.log('处理类型错误:', e.message);
      } else if (e instanceof ReferenceError) {
        console.log('处理引用错误:', e.message);
      } else if (e instanceof RangeError) {
        console.log('处理范围错误:', e.message);
      } else {
        console.log('处理通用错误:', e.message);
      }
    }
  });
}

handleDifferentErrors();

// 自定义错误类型
class CustomError extends Error {
  constructor(message, code, details) {
    super(message);
    this.name = 'CustomError';
    this.code = code;
    this.details = details;
    this.timestamp = new Date().toISOString();
    
    // 确保堆栈跟踪正确
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, CustomError);
    }
  }
  
  toJSON() {
    return {
      name: this.name,
      message: this.message,
      code: this.code,
      details: this.details,
      timestamp: this.timestamp,
      stack: this.stack
    };
  }
}

// 特定的自定义错误类型
class ValidationError extends CustomError {
  constructor(field, value, rule) {
    super(`验证失败: ${field}`, 'VALIDATION_ERROR', {
      field,
      value,
      rule
    });
    this.name = 'ValidationError';
  }
}

class NetworkError extends CustomError {
  constructor(url, status, statusText) {
    super(`网络请求失败: ${status} ${statusText}`, 'NETWORK_ERROR', {
      url,
      status,
      statusText
    });
    this.name = 'NetworkError';
  }
}

class BusinessLogicError extends CustomError {
  constructor(operation, reason) {
    super(`业务逻辑错误: ${operation}`, 'BUSINESS_ERROR', {
      operation,
      reason
    });
    this.name = 'BusinessLogicError';
  }
}

// 使用自定义错误
function validateUser(user) {
  if (!user.name) {
    throw new ValidationError('name', user.name, 'required');
  }
  
  if (user.age < 0 || user.age > 150) {
    throw new ValidationError('age', user.age, 'range:0-150');
  }
  
  if (!user.email || !user.email.includes('@')) {
    throw new ValidationError('email', user.email, 'format:email');
  }
}

function processUser(user) {
  try {
    validateUser(user);
    console.log('用户验证通过:', user.name);
  } catch (error) {
    if (error instanceof ValidationError) {
      console.error('验证错误:', {
        field: error.details.field,
        value: error.details.value,
        rule: error.details.rule,
        timestamp: error.timestamp
      });
    } else {
      console.error('未知错误:', error.message);
    }
  }
}

// 测试自定义错误
processUser({ name: '', age: 25, email: 'test@example.com' });
processUser({ name: '张三', age: -5, email: 'test@example.com' });
processUser({ name: '李四', age: 30, email: 'invalid-email' });
processUser({ name: '王五', age: 25, email: 'test@example.com' });

try-catch-finally语句

// 基本的try-catch-finally结构

function demonstrateTryCatchFinally() {
  console.log('=== try-catch-finally演示 ===');
  
  try {
    console.log('1. 执行try块');
    
    // 模拟可能出错的操作
    const randomError = Math.random() > 0.5;
    if (randomError) {
      throw new Error('随机错误发生了');
    }
    
    console.log('2. try块执行成功');
    return 'success';
    
  } catch (error) {
    console.log('3. 捕获到错误:', error.message);
    return 'error';
    
  } finally {
    console.log('4. finally块总是执行');
    // 注意:finally块中的return会覆盖try/catch中的return
  }
}

// 多次调用查看不同结果
for (let i = 0; i < 3; i++) {
  console.log('结果:', demonstrateTryCatchFinally());
  console.log('---');
}

// 嵌套的try-catch
function nestedTryCatch() {
  try {
    console.log('外层try开始');
    
    try {
      console.log('内层try开始');
      throw new Error('内层错误');
    } catch (innerError) {
      console.log('内层catch:', innerError.message);
      throw new Error('重新抛出的错误');
    } finally {
      console.log('内层finally');
    }
    
  } catch (outerError) {
    console.log('外层catch:', outerError.message);
  } finally {
    console.log('外层finally');
  }
}

nestedTryCatch();

// 资源管理模式
class Resource {
  constructor(name) {
    this.name = name;
    this.isOpen = false;
    console.log(`资源 ${this.name} 创建`);
  }
  
  open() {
    if (this.isOpen) {
      throw new Error(`资源 ${this.name} 已经打开`);
    }
    this.isOpen = true;
    console.log(`资源 ${this.name} 打开`);
  }
  
  use() {
    if (!this.isOpen) {
      throw new Error(`资源 ${this.name} 未打开`);
    }
    console.log(`使用资源 ${this.name}`);
    
    // 模拟使用过程中可能出错
    if (Math.random() > 0.7) {
      throw new Error(`使用资源 ${this.name} 时发生错误`);
    }
  }
  
  close() {
    if (this.isOpen) {
      this.isOpen = false;
      console.log(`资源 ${this.name} 关闭`);
    }
  }
}

function useResource(resourceName) {
  const resource = new Resource(resourceName);
  
  try {
    resource.open();
    resource.use();
    console.log(`资源 ${resourceName} 使用成功`);
  } catch (error) {
    console.error(`资源 ${resourceName} 使用失败:`, error.message);
  } finally {
    // 确保资源总是被正确关闭
    resource.close();
  }
}

// 测试资源管理
useResource('数据库连接');
useResource('文件句柄');
useResource('网络连接');

// 使用with语句模拟的资源管理器
class ResourceManager {
  constructor(resource) {
    this.resource = resource;
  }
  
  async use(callback) {
    try {
      this.resource.open();
      return await callback(this.resource);
    } catch (error) {
      console.error('资源使用错误:', error.message);
      throw error;
    } finally {
      this.resource.close();
    }
  }
}

// 使用资源管理器
async function demonstrateResourceManager() {
  const resource = new Resource('托管资源');
  const manager = new ResourceManager(resource);
  
  try {
    await manager.use(async (res) => {
      res.use();
      // 模拟异步操作
      await new Promise(resolve => setTimeout(resolve, 100));
      console.log('异步操作完成');
    });
  } catch (error) {
    console.error('托管资源使用失败:', error.message);
  }
}

demonstrateResourceManager();

// 错误边界模式(类似React的错误边界)
class ErrorBoundary {
  constructor(fallback) {
    this.fallback = fallback;
    this.hasError = false;
    this.error = null;
  }
  
  wrap(fn) {
    return (...args) => {
      try {
        this.hasError = false;
        this.error = null;
        return fn(...args);
      } catch (error) {
        this.hasError = true;
        this.error = error;
        console.error('ErrorBoundary捕获错误:', error.message);
        return this.fallback(error);
      }
    };
  }
  
  getErrorInfo() {
    return {
      hasError: this.hasError,
      error: this.error
    };
  }
  
  reset() {
    this.hasError = false;
    this.error = null;
  }
}

// 使用错误边界
const errorBoundary = new ErrorBoundary((error) => {
  return `发生错误,显示备用内容: ${error.message}`;
});

const riskyFunction = errorBoundary.wrap((x) => {
  if (x < 0) {
    throw new Error('输入不能为负数');
  }
  return x * 2;
});

console.log(riskyFunction(5));  // 正常执行
console.log(riskyFunction(-3)); // 触发错误边界
console.log('错误信息:', errorBoundary.getErrorInfo());

异步错误处理

Promise错误处理

// Promise中的错误处理

// 1. 使用.catch()方法
function promiseErrorHandling() {
  console.log('=== Promise错误处理 ===');
  
  // 创建一个可能失败的Promise
  function createPromise(shouldFail = false) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (shouldFail) {
          reject(new Error('Promise执行失败'));
        } else {
          resolve('Promise执行成功');
        }
      }, 100);
    });
  }
  
  // 成功的情况
  createPromise(false)
    .then(result => {
      console.log('成功:', result);
    })
    .catch(error => {
      console.error('错误:', error.message);
    });
  
  // 失败的情况
  createPromise(true)
    .then(result => {
      console.log('成功:', result);
    })
    .catch(error => {
      console.error('错误:', error.message);
    });
}

promiseErrorHandling();

// 2. Promise链中的错误传播
function promiseChainErrorHandling() {
  console.log('=== Promise链错误处理 ===');
  
  Promise.resolve(10)
    .then(value => {
      console.log('步骤1:', value);
      return value * 2;
    })
    .then(value => {
      console.log('步骤2:', value);
      if (value > 15) {
        throw new Error('值太大了');
      }
      return value + 5;
    })
    .then(value => {
      console.log('步骤3:', value); // 这一步不会执行
      return value;
    })
    .catch(error => {
      console.error('链中捕获错误:', error.message);
      return 0; // 返回默认值
    })
    .then(value => {
      console.log('最终结果:', value); // 会执行,值为0
    });
}

promiseChainErrorHandling();

// 3. 多个Promise的错误处理
function multiplePromiseErrorHandling() {
  console.log('=== 多个Promise错误处理 ===');
  
  const promises = [
    Promise.resolve('成功1'),
    Promise.reject(new Error('失败2')),
    Promise.resolve('成功3'),
    Promise.reject(new Error('失败4'))
  ];
  
  // Promise.all - 任何一个失败就失败
  Promise.all(promises)
    .then(results => {
      console.log('所有成功:', results);
    })
    .catch(error => {
      console.error('Promise.all失败:', error.message);
    });
  
  // Promise.allSettled - 等待所有完成
  Promise.allSettled(promises)
    .then(results => {
      console.log('Promise.allSettled结果:');
      results.forEach((result, index) => {
        if (result.status === 'fulfilled') {
          console.log(`  ${index}: 成功 -`, result.value);
        } else {
          console.log(`  ${index}: 失败 -`, result.reason.message);
        }
      });
    });
  
  // 手动处理每个Promise的错误
  const safePromises = promises.map(promise => 
    promise.catch(error => ({ error: error.message }))
  );
  
  Promise.all(safePromises)
    .then(results => {
      console.log('安全处理结果:');
      results.forEach((result, index) => {
        if (result.error) {
          console.log(`  ${index}: 错误 -`, result.error);
        } else {
          console.log(`  ${index}: 成功 -`, result);
        }
      });
    });
}

multiplePromiseErrorHandling();

// 4. 重试机制
class RetryablePromise {
  static async retry(fn, maxAttempts = 3, delay = 1000) {
    let lastError;
    
    for (let attempt = 1; attempt <= maxAttempts; attempt++) {
      try {
        console.log(`尝试第 ${attempt} 次`);
        const result = await fn();
        console.log(`第 ${attempt} 次尝试成功`);
        return result;
      } catch (error) {
        lastError = error;
        console.log(`第 ${attempt} 次尝试失败:`, error.message);
        
        if (attempt < maxAttempts) {
          console.log(`等待 ${delay}ms 后重试...`);
          await new Promise(resolve => setTimeout(resolve, delay));
          delay *= 2; // 指数退避
        }
      }
    }
    
    throw new Error(`重试 ${maxAttempts} 次后仍然失败: ${lastError.message}`);
  }
  
  static async retryWithCondition(fn, shouldRetry, maxAttempts = 3, delay = 1000) {
    let lastError;
    
    for (let attempt = 1; attempt <= maxAttempts; attempt++) {
      try {
        const result = await fn();
        return result;
      } catch (error) {
        lastError = error;
        console.log(`第 ${attempt} 次尝试失败:`, error.message);
        
        if (attempt < maxAttempts && shouldRetry(error)) {
          console.log(`错误可重试,等待 ${delay}ms 后重试...`);
          await new Promise(resolve => setTimeout(resolve, delay));
          delay *= 2;
        } else {
          break;
        }
      }
    }
    
    throw lastError;
  }
}

// 使用重试机制
async function demonstrateRetry() {
  console.log('=== 重试机制演示 ===');
  
  // 模拟不稳定的网络请求
  let attemptCount = 0;
  const unstableRequest = () => {
    attemptCount++;
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (Math.random() > 0.7) {
          resolve(`请求成功,尝试了 ${attemptCount} 次`);
        } else {
          reject(new Error(`网络错误 (尝试 ${attemptCount})`);
        }
      }, 100);
    });
  };
  
  try {
    const result = await RetryablePromise.retry(unstableRequest, 5, 200);
    console.log('最终结果:', result);
  } catch (error) {
    console.error('重试失败:', error.message);
  }
  
  // 条件重试示例
  const conditionalRequest = () => {
    const errorTypes = ['NETWORK_ERROR', 'TIMEOUT', 'AUTH_ERROR', 'SERVER_ERROR'];
    const randomError = errorTypes[Math.floor(Math.random() * errorTypes.length)];
    
    return Promise.reject(new NetworkError('https://api.example.com', 500, randomError));
  };
  
  try {
    await RetryablePromise.retryWithCondition(
      conditionalRequest,
      (error) => {
        // 只重试网络错误和超时错误
        return error.details.statusText === 'NETWORK_ERROR' || 
               error.details.statusText === 'TIMEOUT';
      },
      3,
      500
    );
  } catch (error) {
    console.error('条件重试失败:', error.message);
  }
}

demonstrateRetry();

async/await错误处理

// async/await中的错误处理

// 1. 基本的async/await错误处理
async function basicAsyncErrorHandling() {
  console.log('=== async/await基本错误处理 ===');
  
  async function riskyAsyncFunction(shouldFail = false) {
    await new Promise(resolve => setTimeout(resolve, 100));
    
    if (shouldFail) {
      throw new Error('异步函数执行失败');
    }
    
    return '异步函数执行成功';
  }
  
  // 成功的情况
  try {
    const result = await riskyAsyncFunction(false);
    console.log('成功:', result);
  } catch (error) {
    console.error('错误:', error.message);
  }
  
  // 失败的情况
  try {
    const result = await riskyAsyncFunction(true);
    console.log('成功:', result);
  } catch (error) {
    console.error('错误:', error.message);
  }
}

basicAsyncErrorHandling();

// 2. 多个异步操作的错误处理
async function multipleAsyncErrorHandling() {
  console.log('=== 多个异步操作错误处理 ===');
  
  async function fetchData(id, shouldFail = false) {
    await new Promise(resolve => setTimeout(resolve, Math.random() * 200));
    
    if (shouldFail) {
      throw new Error(`获取数据 ${id} 失败`);
    }
    
    return `数据 ${id}`;
  }
  
  // 顺序执行,遇到错误就停止
  try {
    const data1 = await fetchData(1, false);
    console.log('获取到:', data1);
    
    const data2 = await fetchData(2, true); // 这里会失败
    console.log('获取到:', data2);
    
    const data3 = await fetchData(3, false); // 不会执行
    console.log('获取到:', data3);
  } catch (error) {
    console.error('顺序执行失败:', error.message);
  }
  
  // 并行执行,处理部分失败
  const results = await Promise.allSettled([
    fetchData(4, false),
    fetchData(5, true),
    fetchData(6, false)
  ]);
  
  console.log('并行执行结果:');
  results.forEach((result, index) => {
    if (result.status === 'fulfilled') {
      console.log(`  数据 ${index + 4}: 成功 -`, result.value);
    } else {
      console.log(`  数据 ${index + 4}: 失败 -`, result.reason.message);
    }
  });
}

multipleAsyncErrorHandling();

// 3. 异步错误处理工具类
class AsyncErrorHandler {
  // 安全执行异步函数
  static async safe(asyncFn, defaultValue = null) {
    try {
      return await asyncFn();
    } catch (error) {
      console.error('AsyncErrorHandler.safe捕获错误:', error.message);
      return defaultValue;
    }
  }
  
  // 带超时的异步执行
  static async withTimeout(asyncFn, timeoutMs = 5000) {
    const timeoutPromise = new Promise((_, reject) => {
      setTimeout(() => {
        reject(new Error(`操作超时 (${timeoutMs}ms)`));
      }, timeoutMs);
    });
    
    return Promise.race([asyncFn(), timeoutPromise]);
  }
  
  // 批量执行异步操作,收集所有结果
  static async batch(asyncFunctions, concurrency = 3) {
    const results = [];
    const errors = [];
    
    // 分批执行
    for (let i = 0; i < asyncFunctions.length; i += concurrency) {
      const batch = asyncFunctions.slice(i, i + concurrency);
      const batchResults = await Promise.allSettled(
        batch.map(fn => fn())
      );
      
      batchResults.forEach((result, index) => {
        const globalIndex = i + index;
        if (result.status === 'fulfilled') {
          results[globalIndex] = result.value;
        } else {
          errors[globalIndex] = result.reason;
        }
      });
    }
    
    return { results, errors };
  }
  
  // 带重试的异步执行
  static async withRetry(asyncFn, options = {}) {
    const {
      maxAttempts = 3,
      delay = 1000,
      backoff = 2,
      shouldRetry = () => true
    } = options;
    
    let lastError;
    let currentDelay = delay;
    
    for (let attempt = 1; attempt <= maxAttempts; attempt++) {
      try {
        return await asyncFn();
      } catch (error) {
        lastError = error;
        
        if (attempt < maxAttempts && shouldRetry(error)) {
          console.log(`重试第 ${attempt} 次失败,${currentDelay}ms后重试`);
          await new Promise(resolve => setTimeout(resolve, currentDelay));
          currentDelay *= backoff;
        } else {
          break;
        }
      }
    }
    
    throw lastError;
  }
}

// 使用异步错误处理工具
async function demonstrateAsyncErrorHandler() {
  console.log('=== 异步错误处理工具演示 ===');
  
  // 安全执行
  const safeResult = await AsyncErrorHandler.safe(
    async () => {
      throw new Error('这会失败');
    },
    '默认值'
  );
  console.log('安全执行结果:', safeResult);
  
  // 超时控制
  try {
    await AsyncErrorHandler.withTimeout(
      async () => {
        await new Promise(resolve => setTimeout(resolve, 3000));
        return '慢操作完成';
      },
      1000
    );
  } catch (error) {
    console.error('超时错误:', error.message);
  }
  
  // 批量执行
  const asyncTasks = [
    async () => { await new Promise(r => setTimeout(r, 100)); return '任务1'; },
    async () => { throw new Error('任务2失败'); },
    async () => { await new Promise(r => setTimeout(r, 200)); return '任务3'; },
    async () => { await new Promise(r => setTimeout(r, 150)); return '任务4'; }
  ];
  
  const { results, errors } = await AsyncErrorHandler.batch(asyncTasks, 2);
  console.log('批量执行结果:', results);
  console.log('批量执行错误:', errors);
  
  // 带重试的执行
  let retryCount = 0;
  try {
    const retryResult = await AsyncErrorHandler.withRetry(
      async () => {
        retryCount++;
        if (retryCount < 3) {
          throw new Error(`第${retryCount}次尝试失败`);
        }
        return '重试成功';
      },
      {
        maxAttempts: 5,
        delay: 100,
        backoff: 1.5
      }
    );
    console.log('重试结果:', retryResult);
  } catch (error) {
    console.error('重试最终失败:', error.message);
  }
}

demonstrateAsyncErrorHandler();

调试技巧和工具

浏览器调试工具

// 浏览器调试技巧

// 1. console对象的高级用法
function advancedConsoleUsage() {
  console.log('=== 高级Console用法 ===');
  
  // 基本日志级别
  console.log('普通日志');
  console.info('信息日志');
  console.warn('警告日志');
  console.error('错误日志');
  
  // 分组日志
  console.group('用户操作');
  console.log('用户登录');
  console.log('用户浏览商品');
  console.groupCollapsed('购买流程'); // 默认折叠
  console.log('添加到购物车');
  console.log('结算');
  console.log('支付');
  console.groupEnd();
  console.groupEnd();
  
  // 表格显示
  const users = [
    { id: 1, name: '张三', age: 25, city: '北京' },
    { id: 2, name: '李四', age: 30, city: '上海' },
    { id: 3, name: '王五', age: 28, city: '广州' }
  ];
  console.table(users);
  
  // 计时
  console.time('数组排序');
  const largeArray = Array.from({ length: 100000 }, () => Math.random());
  largeArray.sort();
  console.timeEnd('数组排序');
  
  // 计数
  for (let i = 0; i < 5; i++) {
    console.count('循环计数');
  }
  console.countReset('循环计数');
  
  // 断言
  console.assert(2 + 2 === 4, '数学没问题');
  console.assert(2 + 2 === 5, '数学有问题', { expected: 5, actual: 4 });
  
  // 堆栈跟踪
  function level1() {
    function level2() {
      function level3() {
        console.trace('堆栈跟踪');
      }
      level3();
    }
    level2();
  }
  level1();
  
  // 样式化输出
  console.log('%c这是红色文字', 'color: red; font-size: 16px; font-weight: bold;');
  console.log('%c这是蓝色背景', 'background: blue; color: white; padding: 5px;');
  
  // 目录显示
  const complexObject = {
    user: {
      profile: {
        personal: { name: '张三', age: 25 },
        contact: { email: 'zhangsan@example.com', phone: '138-0013-8000' }
      },
      preferences: {
        theme: 'dark',
        language: 'zh-CN'
      }
    }
  };
  console.dir(complexObject, { depth: null });
}

advancedConsoleUsage();

// 2. 调试器和断点
function debuggerUsage() {
  console.log('=== 调试器使用 ===');
  
  function calculateSum(numbers) {
    let sum = 0;
    
    for (let i = 0; i < numbers.length; i++) {
      // 在开发者工具中,这里会暂停执行
      // debugger;
      
      sum += numbers[i];
      
      // 条件断点示例
      if (sum > 100) {
        console.log('总和超过100:', sum);
        // debugger; // 只有当sum > 100时才暂停
      }
    }
    
    return sum;
  }
  
  const numbers = [10, 20, 30, 40, 50];
  const result = calculateSum(numbers);
  console.log('计算结果:', result);
}

debuggerUsage();

// 3. 性能监控
class PerformanceMonitor {
  static measure(name, fn) {
    const start = performance.now();
    const result = fn();
    const end = performance.now();
    
    console.log(`${name} 执行时间: ${(end - start).toFixed(2)}ms`);
    return result;
  }
  
  static async measureAsync(name, asyncFn) {
    const start = performance.now();
    const result = await asyncFn();
    const end = performance.now();
    
    console.log(`${name} 执行时间: ${(end - start).toFixed(2)}ms`);
    return result;
  }
  
  static profile(name, fn, iterations = 1000) {
    const times = [];
    
    for (let i = 0; i < iterations; i++) {
      const start = performance.now();
      fn();
      const end = performance.now();
      times.push(end - start);
    }
    
    const avg = times.reduce((sum, time) => sum + time, 0) / times.length;
    const min = Math.min(...times);
    const max = Math.max(...times);
    
    console.log(`${name} 性能分析 (${iterations}次):`);
    console.log(`  平均: ${avg.toFixed(4)}ms`);
    console.log(`  最小: ${min.toFixed(4)}ms`);
    console.log(`  最大: ${max.toFixed(4)}ms`);
    
    return { avg, min, max, times };
  }
  
  static memoryUsage() {
    if (performance.memory) {
      const memory = performance.memory;
      console.log('内存使用情况:');
      console.log(`  已用: ${(memory.usedJSHeapSize / 1024 / 1024).toFixed(2)}MB`);
      console.log(`  总计: ${(memory.totalJSHeapSize / 1024 / 1024).toFixed(2)}MB`);
      console.log(`  限制: ${(memory.jsHeapSizeLimit / 1024 / 1024).toFixed(2)}MB`);
      return memory;
    } else {
      console.log('浏览器不支持内存监控');
      return null;
    }
  }
}

// 使用性能监控
function demonstratePerformanceMonitoring() {
  console.log('=== 性能监控演示 ===');
  
  // 测量同步函数
  PerformanceMonitor.measure('数组创建', () => {
    return Array.from({ length: 10000 }, (_, i) => i * 2);
  });
  
  // 测量异步函数
  PerformanceMonitor.measureAsync('异步延迟', async () => {
    await new Promise(resolve => setTimeout(resolve, 100));
    return '完成';
  });
  
  // 性能分析
  PerformanceMonitor.profile('字符串拼接', () => {
    let str = '';
    for (let i = 0; i < 100; i++) {
      str += 'a';
    }
    return str;
  }, 1000);
  
  PerformanceMonitor.profile('数组join', () => {
    const arr = new Array(100).fill('a');
    return arr.join('');
  }, 1000);
  
  // 内存使用
  PerformanceMonitor.memoryUsage();
}

demonstratePerformanceMonitoring();

// 4. 错误监控和报告
class ErrorReporter {
  constructor() {
    this.errors = [];
    this.setupGlobalErrorHandling();
  }
  
  setupGlobalErrorHandling() {
    // 捕获未处理的错误
    window.addEventListener('error', (event) => {
      this.reportError({
        type: 'javascript',
        message: event.message,
        filename: event.filename,
        lineno: event.lineno,
        colno: event.colno,
        error: event.error,
        timestamp: new Date().toISOString()
      });
    });
    
    // 捕获未处理的Promise拒绝
    window.addEventListener('unhandledrejection', (event) => {
      this.reportError({
        type: 'promise',
        message: event.reason?.message || '未处理的Promise拒绝',
        reason: event.reason,
        timestamp: new Date().toISOString()
      });
    });
  }
  
  reportError(errorInfo) {
    this.errors.push(errorInfo);
    console.error('错误报告:', errorInfo);
    
    // 在实际应用中,这里会发送到错误监控服务
    this.sendToErrorService(errorInfo);
  }
  
  sendToErrorService(errorInfo) {
    // 模拟发送到错误监控服务
    console.log('发送错误到监控服务:', {
      ...errorInfo,
      userAgent: navigator.userAgent,
      url: window.location.href,
      userId: this.getCurrentUserId()
    });
  }
  
  getCurrentUserId() {
    // 模拟获取当前用户ID
    return 'user_123';
  }
  
  getErrorSummary() {
    const summary = {
      total: this.errors.length,
      byType: {},
      recent: this.errors.slice(-5)
    };
    
    this.errors.forEach(error => {
      summary.byType[error.type] = (summary.byType[error.type] || 0) + 1;
    });
    
    return summary;
  }
  
  clearErrors() {
    this.errors = [];
  }
}

// 使用错误报告器
const errorReporter = new ErrorReporter();

// 模拟一些错误
setTimeout(() => {
  // 这会触发全局错误处理
  // throw new Error('模拟的JavaScript错误');
}, 1000);

setTimeout(() => {
  // 这会触发未处理的Promise拒绝
  Promise.reject(new Error('模拟的Promise错误'));
}, 2000);

setTimeout(() => {
  console.log('错误摘要:', errorReporter.getErrorSummary());
}, 3000);

日志系统

// 完整的日志系统实现

class Logger {
  constructor(options = {}) {
    this.level = options.level || 'info';
    this.prefix = options.prefix || '';
    this.outputs = options.outputs || [new ConsoleOutput()];
    this.formatters = options.formatters || [new DefaultFormatter()];
    
    this.levels = {
      error: 0,
      warn: 1,
      info: 2,
      debug: 3,
      trace: 4
    };
  }
  
  log(level, message, ...args) {
    if (this.levels[level] <= this.levels[this.level]) {
      const logEntry = {
        level,
        message,
        args,
        timestamp: new Date(),
        prefix: this.prefix
      };
      
      this.outputs.forEach(output => {
        this.formatters.forEach(formatter => {
          const formatted = formatter.format(logEntry);
          output.write(formatted);
        });
      });
    }
  }
  
  error(message, ...args) {
    this.log('error', message, ...args);
  }
  
  warn(message, ...args) {
    this.log('warn', message, ...args);
  }
  
  info(message, ...args) {
    this.log('info', message, ...args);
  }
  
  debug(message, ...args) {
    this.log('debug', message, ...args);
  }
  
  trace(message, ...args) {
    this.log('trace', message, ...args);
  }
  
  child(prefix) {
    return new Logger({
      level: this.level,
      prefix: this.prefix ? `${this.prefix}:${prefix}` : prefix,
      outputs: this.outputs,
      formatters: this.formatters
    });
  }
}

// 格式化器
class DefaultFormatter {
  format(logEntry) {
    const timestamp = logEntry.timestamp.toISOString();
    const level = logEntry.level.toUpperCase().padEnd(5);
    const prefix = logEntry.prefix ? `[${logEntry.prefix}] ` : '';
    
    return {
      timestamp,
      level,
      message: `${timestamp} ${level} ${prefix}${logEntry.message}`,
      args: logEntry.args
    };
  }
}

class JSONFormatter {
  format(logEntry) {
    return {
      timestamp: logEntry.timestamp.toISOString(),
      level: logEntry.level,
      prefix: logEntry.prefix,
      message: logEntry.message,
      args: logEntry.args
    };
  }
}

// 输出器
class ConsoleOutput {
  write(formatted) {
    const method = this.getConsoleMethod(formatted.level);
    if (formatted.args && formatted.args.length > 0) {
      console[method](formatted.message, ...formatted.args);
    } else {
      console[method](formatted.message);
    }
  }
  
  getConsoleMethod(level) {
    switch (level.toLowerCase().trim()) {
      case 'error': return 'error';
      case 'warn': return 'warn';
      case 'debug': return 'debug';
      case 'trace': return 'trace';
      default: return 'log';
    }
  }
}

class MemoryOutput {
  constructor(maxEntries = 1000) {
    this.entries = [];
    this.maxEntries = maxEntries;
  }
  
  write(formatted) {
    this.entries.push(formatted);
    if (this.entries.length > this.maxEntries) {
      this.entries.shift();
    }
  }
  
  getEntries(level = null) {
    if (level) {
      return this.entries.filter(entry => 
        entry.level.toLowerCase().trim() === level.toLowerCase()
      );
    }
    return [...this.entries];
  }
  
  clear() {
    this.entries = [];
  }
}

class RemoteOutput {
  constructor(endpoint, batchSize = 10, flushInterval = 5000) {
    this.endpoint = endpoint;
    this.batchSize = batchSize;
    this.flushInterval = flushInterval;
    this.buffer = [];
    
    // 定期刷新缓冲区
    setInterval(() => this.flush(), flushInterval);
    
    // 页面卸载时刷新
    window.addEventListener('beforeunload', () => this.flush());
  }
  
  write(formatted) {
    this.buffer.push(formatted);
    if (this.buffer.length >= this.batchSize) {
      this.flush();
    }
  }
  
  async flush() {
    if (this.buffer.length === 0) return;
    
    const logs = [...this.buffer];
    this.buffer = [];
    
    try {
      await fetch(this.endpoint, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ logs })
      });
    } catch (error) {
      console.error('发送日志失败:', error);
      // 失败的日志重新加入缓冲区
      this.buffer.unshift(...logs);
    }
  }
}

// 使用日志系统
function demonstrateLoggingSystem() {
  console.log('=== 日志系统演示 ===');
  
  // 创建内存输出器用于演示
  const memoryOutput = new MemoryOutput();
  
  // 创建主日志器
  const logger = new Logger({
    level: 'debug',
    outputs: [new ConsoleOutput(), memoryOutput],
    formatters: [new DefaultFormatter()]
  });
  
  // 基本日志
  logger.info('应用启动');
  logger.debug('调试信息', { userId: 123, action: 'login' });
  logger.warn('警告:内存使用率较高', { usage: '85%' });
  logger.error('错误:数据库连接失败', new Error('连接超时'));
  
  // 创建子日志器
  const userLogger = logger.child('UserService');
  const dbLogger = logger.child('Database');
  
  userLogger.info('用户登录', { userId: 123, username: 'zhangsan' });
  userLogger.debug('验证用户权限');
  
  dbLogger.warn('查询执行缓慢', { query: 'SELECT * FROM users', duration: '2.5s' });
  dbLogger.error('连接池耗尽');
  
  // 查看内存中的日志
  console.log('\n内存中的所有日志:');
  memoryOutput.getEntries().forEach(entry => {
    console.log(entry.message);
  });
  
  console.log('\n只显示错误日志:');
  memoryOutput.getEntries('error').forEach(entry => {
    console.log(entry.message);
  });
}

demonstrateLoggingSystem();

// 日志分析工具
class LogAnalyzer {
  constructor(memoryOutput) {
    this.memoryOutput = memoryOutput;
  }
  
  getStatistics() {
    const entries = this.memoryOutput.getEntries();
    const stats = {
      total: entries.length,
      byLevel: {},
      byPrefix: {},
      timeRange: null
    };
    
    if (entries.length > 0) {
      const timestamps = entries.map(e => new Date(e.timestamp));
      stats.timeRange = {
        start: new Date(Math.min(...timestamps)),
        end: new Date(Math.max(...timestamps))
      };
    }
    
    entries.forEach(entry => {
      const level = entry.level.toLowerCase().trim();
      stats.byLevel[level] = (stats.byLevel[level] || 0) + 1;
      
      // 从消息中提取前缀
      const prefixMatch = entry.message.match(/\[([^\]]+)\]/);
      if (prefixMatch) {
        const prefix = prefixMatch[1];
        stats.byPrefix[prefix] = (stats.byPrefix[prefix] || 0) + 1;
      }
    });
    
    return stats;
  }
  
  findErrors() {
    return this.memoryOutput.getEntries('error');
  }
  
  findPattern(pattern) {
    const regex = new RegExp(pattern, 'i');
    return this.memoryOutput.getEntries().filter(entry => 
      regex.test(entry.message)
    );
  }
  
  getRecentLogs(minutes = 5) {
    const cutoff = new Date(Date.now() - minutes * 60 * 1000);
    return this.memoryOutput.getEntries().filter(entry => 
      new Date(entry.timestamp) > cutoff
    );
  }
}

本章总结

本章全面介绍了JavaScript的错误处理与调试:

  1. 错误类型和异常处理:学习了JavaScript中的各种错误类型、try-catch-finally语句和自定义错误类型
  2. 异步错误处理:掌握了Promise和async/await中的错误处理机制,以及重试和超时控制
  3. 调试技巧和工具:了解了浏览器调试工具的高级用法、性能监控和错误报告
  4. 日志系统:学习了如何构建完整的日志系统,包括格式化器、输出器和日志分析

良好的错误处理和调试能力是JavaScript开发者的重要技能。通过合理的错误处理策略、有效的调试技巧和完善的日志系统,我们可以构建更加健壮和可维护的应用程序。

至此,JavaScript教程的核心内容已经完成。这些知识涵盖了从基础语法到高级特性的各个方面,为深入学习和实际开发奠定了坚实的基础。