Skip to content

JavaScript 静态方法

静态方法是属于类本身而不是类实例的方法。它们不能通过类的实例访问,只能通过类本身调用。静态方法在工具类、工厂方法、配置管理等场景中非常有用。在本章节中,我们将深入学习 JavaScript 中的静态方法。

什么是静态方法

静态方法是直接定义在类上的方法,而不是定义在类的原型上。它们与类的实例无关,通常用于执行与类相关但不需要实例化的操作。

静态方法的特点

  1. 属于类本身:通过类名直接调用,不需要创建实例
  2. 不能访问实例属性:静态方法中无法使用 [this](file:///C:/Workspace/Coding/WebProjects/tutorials-web/node_modules/typescript/lib/lib.es2022.intl.d.ts#L2-L2) 访问实例属性
  3. 可以访问静态属性:可以访问类的静态属性和其他静态方法
  4. 内存效率:不需要创建实例就能使用,节省内存

基本语法

ES6 静态方法

javascript
class MathUtils {
  // 静态方法
  static add(a, b) {
    return a + b;
  }
  
  static multiply(a, b) {
    return a * b;
  }
  
  static power(base, exponent) {
    return Math.pow(base, exponent);
  }
  
  // 静态属性(ES2022)
  static PI = 3.14159;
  
  // 实例方法
  calculateArea(radius) {
    return MathUtils.PI * radius * radius; // 访问静态属性
  }
  
  // 实例方法
  calculateCircumference(radius) {
    return 2 * MathUtils.PI * radius; // 访问静态属性
  }
}

// 调用静态方法
console.log(MathUtils.add(5, 3)); // 8
console.log(MathUtils.multiply(4, 6)); // 24
console.log(MathUtils.power(2, 3)); // 8
console.log(MathUtils.PI); // 3.14159

// 创建实例并调用实例方法
const utils = new MathUtils();
console.log(utils.calculateArea(5)); // 78.53975
console.log(utils.calculateCircumference(5)); // 31.4159

// 错误示例:不能通过实例调用静态方法
// console.log(utils.add(1, 2)); // TypeError: utils.add is not a function

ES5 静态方法

javascript
// ES5 中定义静态方法
function StringUtils() {
  // 构造函数
}

// 静态方法
StringUtils.capitalize = function(str) {
  if (!str) return str;
  return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
};

StringUtils.reverse = function(str) {
  if (!str) return str;
  return str.split("").reverse().join("");
};

StringUtils.isPalindrome = function(str) {
  if (!str) return false;
  const cleaned = str.toLowerCase().replace(/[^a-z0-9]/g, "");
  return cleaned === cleaned.split("").reverse().join("");
};

// 使用静态方法
console.log(StringUtils.capitalize("hello world")); // "Hello world"
console.log(StringUtils.reverse("hello")); // "olleh"
console.log(StringUtils.isPalindrome("A man a plan a canal Panama")); // true

// 创建实例
const stringUtils = new StringUtils();
console.log(typeof stringUtils.capitalize); // "undefined"

静态方法的应用场景

1. 工具类方法

javascript
class DateUtils {
  // 格式化日期
  static formatDate(date, format = "YYYY-MM-DD") {
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, "0");
    const day = String(date.getDate()).padStart(2, "0");
    
    return format
      .replace("YYYY", year)
      .replace("MM", month)
      .replace("DD", day);
  }
  
  // 计算两个日期之间的天数
  static daysBetween(date1, date2) {
    const oneDay = 24 * 60 * 60 * 1000; // 小时*分钟*秒*毫秒
    const firstDate = new Date(date1);
    const secondDate = new Date(date2);
    
    return Math.round(Math.abs((firstDate - secondDate) / oneDay));
  }
  
  // 获取当前时间戳
  static now() {
    return Date.now();
  }
  
  // 验证日期格式
  static isValidDate(dateString) {
    const date = new Date(dateString);
    return date !== "Invalid Date" && !isNaN(date);
  }
  
  // 获取月份的天数
  static getDaysInMonth(year, month) {
    return new Date(year, month, 0).getDate();
  }
}

// 使用示例
const today = new Date();
console.log(DateUtils.formatDate(today)); // "2024-01-15"
console.log(DateUtils.formatDate(today, "DD/MM/YYYY")); // "15/01/2024"

const date1 = new Date("2024-01-01");
const date2 = new Date("2024-01-15");
console.log(DateUtils.daysBetween(date1, date2)); // 14

console.log(DateUtils.isValidDate("2024-01-15")); // true
console.log(DateUtils.isValidDate("invalid date")); // false

console.log(DateUtils.getDaysInMonth(2024, 2)); // 29 (2024年是闰年)

2. 工厂方法

javascript
class User {
  constructor(id, name, email, role = "user") {
    this.id = id;
    this.name = name;
    this.email = email;
    this.role = role;
    this.createdAt = new Date();
  }
  
  // 静态工厂方法
  static createAdmin(name, email) {
    const id = this.generateId();
    return new User(id, name, email, "admin");
  }
  
  static createCustomer(name, email) {
    const id = this.generateId();
    return new User(id, name, email, "customer");
  }
  
  static createGuest() {
    const id = this.generateId();
    return new User(id, "访客", "guest@example.com", "guest");
  }
  
  // 私有静态方法(生成唯一ID)
  static generateId() {
    return Date.now().toString(36) + Math.random().toString(36).substr(2, 5);
  }
  
  // 静态方法:从 JSON 创建用户
  static fromJSON(jsonString) {
    const data = JSON.parse(jsonString);
    return new User(data.id, data.name, data.email, data.role);
  }
  
  // 静态方法:验证用户数据
  static validate(userData) {
    const errors = [];
    
    if (!userData.name || userData.name.trim().length === 0) {
      errors.push("姓名不能为空");
    }
    
    if (!userData.email || !userData.email.includes("@")) {
      errors.push("邮箱格式不正确");
    }
    
    return {
      valid: errors.length === 0,
      errors: errors
    };
  }
  
  getInfo() {
    return {
      id: this.id,
      name: this.name,
      email: this.email,
      role: this.role,
      createdAt: this.createdAt
    };
  }
  
  toJSON() {
    return JSON.stringify(this.getInfo());
  }
}

// 使用工厂方法创建不同类型的用户
const admin = User.createAdmin("管理员", "admin@example.com");
const customer = User.createCustomer("顾客", "customer@example.com");
const guest = User.createGuest();

console.log(admin.getInfo());
console.log(customer.getInfo());
console.log(guest.getInfo());

// 使用 fromJSON 方法
const userJson = '{"id":"123","name":"张三","email":"zhangsan@example.com","role":"user"}';
const userFromJson = User.fromJSON(userJson);
console.log(userFromJson.getInfo());

// 验证用户数据
const validationResult = User.validate({ name: "张三", email: "zhangsan@example.com" });
console.log(validationResult); // { valid: true, errors: [] }

const invalidResult = User.validate({ name: "", email: "invalid" });
console.log(invalidResult); // { valid: false, errors: ["姓名不能为空", "邮箱格式不正确"] }

3. 配置管理

javascript
class Config {
  // 静态属性存储配置
  static #config = new Map();
  
  // 默认配置
  static #defaults = {
    apiUrl: "https://api.example.com",
    timeout: 5000,
    retries: 3,
    debug: false
  };
  
  // 设置配置项
  static set(key, value) {
    this.#config.set(key, value);
  }
  
  // 获取配置项
  static get(key) {
    if (this.#config.has(key)) {
      return this.#config.get(key);
    }
    
    if (key in this.#defaults) {
      return this.#defaults[key];
    }
    
    return undefined;
  }
  
  // 批量设置配置
  static setBatch(configObject) {
    Object.entries(configObject).forEach(([key, value]) => {
      this.set(key, value);
    });
  }
  
  // 获取所有配置
  static getAll() {
    const result = { ...this.#defaults };
    
    for (const [key, value] of this.#config) {
      result[key] = value;
    }
    
    return result;
  }
  
  // 重置配置
  static reset() {
    this.#config.clear();
  }
  
  // 验证配置
  static validate() {
    const errors = [];
    const config = this.getAll();
    
    if (typeof config.timeout !== "number" || config.timeout <= 0) {
      errors.push("timeout 必须是正数");
    }
    
    if (typeof config.retries !== "number" || config.retries < 0) {
      errors.push("retries 必须是非负数");
    }
    
    if (typeof config.debug !== "boolean") {
      errors.push("debug 必须是布尔值");
    }
    
    return {
      valid: errors.length === 0,
      errors: errors
    };
  }
  
  // 加载配置文件
  static async loadFromFile(filePath) {
    try {
      // 模拟异步加载配置文件
      const configFile = await this.#readConfigFile(filePath);
      this.setBatch(configFile);
      return true;
    } catch (error) {
      console.error("加载配置文件失败:", error);
      return false;
    }
  }
  
  // 模拟读取配置文件
  static async #readConfigFile(filePath) {
    // 在实际应用中,这里会读取文件内容
    // 这里返回模拟数据
    return {
      apiUrl: "https://production-api.example.com",
      timeout: 10000,
      retries: 5,
      debug: true
    };
  }
  
  // 导出配置
  static export() {
    return JSON.stringify(this.getAll(), null, 2);
  }
  
  // 导入配置
  static import(configString) {
    try {
      const config = JSON.parse(configString);
      this.setBatch(config);
      return true;
    } catch (error) {
      console.error("导入配置失败:", error);
      return false;
    }
  }
}

// 使用示例
console.log(Config.get("apiUrl")); // "https://api.example.com" (默认值)
console.log(Config.get("timeout")); // 5000 (默认值)

Config.set("apiUrl", "https://custom-api.example.com");
Config.set("customField", "自定义值");

console.log(Config.get("apiUrl")); // "https://custom-api.example.com"
console.log(Config.get("customField")); // "自定义值"

console.log("所有配置:", Config.getAll());

// 验证配置
const validation = Config.validate();
console.log("配置验证:", validation);

// 导出和导入配置
const exportedConfig = Config.export();
console.log("导出的配置:", exportedConfig);

Config.reset();
console.log("重置后的配置:", Config.getAll());

Config.import(exportedConfig);
console.log("导入后的配置:", Config.getAll());

静态方法与实例方法的区别

访问权限

javascript
class Example {
  constructor(value) {
    this.instanceValue = value;
  }
  
  // 实例方法
  instanceMethod() {
    console.log("实例方法可以访问:");
    console.log("- this.instanceValue:", this.instanceValue);
    console.log("- 静态属性:", Example.staticProperty);
    console.log("- 静态方法:", Example.staticMethod());
  }
  
  // 实例方法不能直接访问静态属性(需要通过类名)
  // instanceMethod() {
  //   console.log(this.staticProperty); // undefined
  // }
  
  // 静态方法
  static staticMethod() {
    console.log("静态方法可以访问:");
    console.log("- 静态属性:", this.staticProperty);
    console.log("- 其他静态方法:", this.anotherStaticMethod());
    // console.log(this.instanceValue); // 错误:无法访问实例属性
    return "静态方法返回值";
  }
  
  static anotherStaticMethod() {
    return "另一个静态方法";
  }
  
  // 静态属性
  static staticProperty = "静态属性值";
}

const instance = new Example("实例值");

// 调用实例方法
instance.instanceMethod();

// 调用静态方法
Example.staticMethod();

// 错误示例
// instance.staticMethod(); // TypeError: instance.staticMethod is not a function

继承中的静态方法

javascript
class Parent {
  constructor(name) {
    this.name = name;
  }
  
  // 实例方法
  greet() {
    return `你好,我是${this.name}`;
  }
  
  // 静态方法
  static getType() {
    return "Parent";
  }
  
  static createDefault() {
    return new this("默认名称"); // this 指向调用的类
  }
  
  static getClassName() {
    return this.name; // this 指向调用的类
  }
}

class Child extends Parent {
  constructor(name, age) {
    super(name);
    this.age = age;
  }
  
  // 重写实例方法
  greet() {
    return `${super.greet()},今年${this.age}岁`;
  }
  
  // 重写静态方法
  static getType() {
    return "Child";
  }
  
  // 特有的静态方法
  static createTeenager(name) {
    return new this(name, 16);
  }
}

// 使用示例
const parent = new Parent("父类实例");
const child = new Child("子类实例", 25);

console.log(parent.greet()); // "你好,我是父类实例"
console.log(child.greet()); // "你好,我是子类实例,今年25岁"

// 静态方法调用
console.log(Parent.getType()); // "Parent"
console.log(Child.getType()); // "Child"

// 继承的静态方法
const defaultParent = Parent.createDefault();
const defaultChild = Child.createDefault();
console.log(defaultParent.greet()); // "你好,我是默认名称"
console.log(defaultChild.greet()); // "你好,我是默认名称"

console.log(Parent.getClassName()); // "Parent"
console.log(Child.getClassName()); // "Child"

// 子类特有的静态方法
const teenager = Child.createTeenager("青少年");
console.log(teenager.greet()); // "你好,我是青少年,今年16岁"

静态方法的最佳实践

1. 单例模式

javascript
class DatabaseConnection {
  constructor() {
    if (DatabaseConnection.instance) {
      return DatabaseConnection.instance;
    }
    
    this.connectionString = "default_connection_string";
    this.isConnected = false;
    
    DatabaseConnection.instance = this;
  }
  
  // 静态方法获取单例实例
  static getInstance() {
    if (!DatabaseConnection.instance) {
      DatabaseConnection.instance = new DatabaseConnection();
    }
    return DatabaseConnection.instance;
  }
  
  connect(connectionString) {
    this.connectionString = connectionString || this.connectionString;
    this.isConnected = true;
    return `连接到数据库: ${this.connectionString}`;
  }
  
  disconnect() {
    this.isConnected = false;
    return "断开数据库连接";
  }
  
  query(sql) {
    if (!this.isConnected) {
      throw new Error("数据库未连接");
    }
    return `执行查询: ${sql}`;
  }
  
  // 静态方法直接操作单例
  static executeQuery(sql) {
    const instance = this.getInstance();
    if (!instance.isConnected) {
      instance.connect();
    }
    return instance.query(sql);
  }
}

// 使用示例
const db1 = DatabaseConnection.getInstance();
const db2 = DatabaseConnection.getInstance();

console.log(db1 === db2); // true (同一个实例)

console.log(db1.connect("mysql://localhost:3306/mydb"));
console.log(db2.query("SELECT * FROM users")); // 可以通过 db2 访问

// 使用静态方法
console.log(DatabaseConnection.executeQuery("SELECT * FROM products"));

2. 实用工具类

javascript
class ArrayUtils {
  // 数组去重
  static unique(array) {
    return [...new Set(array)];
  }
  
  // 数组分组
  static groupBy(array, keyFunction) {
    return array.reduce((groups, item) => {
      const key = keyFunction(item);
      if (!groups[key]) {
        groups[key] = [];
      }
      groups[key].push(item);
      return groups;
    }, {});
  }
  
  // 数组排序
  static sortBy(array, key, descending = false) {
    return array.sort((a, b) => {
      const aValue = typeof key === "function" ? key(a) : a[key];
      const bValue = typeof key === "function" ? key(b) : b[key];
      
      if (aValue < bValue) return descending ? 1 : -1;
      if (aValue > bValue) return descending ? -1 : 1;
      return 0;
    });
  }
  
  // 数组扁平化
  static flatten(array, depth = 1) {
    if (depth <= 0) return array.slice();
    
    return array.reduce((acc, val) => {
      return acc.concat(Array.isArray(val) ? this.flatten(val, depth - 1) : val);
    }, []);
  }
  
  // 数组随机排序
  static shuffle(array) {
    const result = [...array];
    for (let i = result.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [result[i], result[j]] = [result[j], result[i]];
    }
    return result;
  }
  
  // 获取数组中的最大值
  static max(array, keyFunction) {
    if (array.length === 0) return undefined;
    
    if (keyFunction) {
      return array.reduce((max, current) => 
        keyFunction(current) > keyFunction(max) ? current : max
      );
    }
    
    return Math.max(...array);
  }
  
  // 获取数组中的最小值
  static min(array, keyFunction) {
    if (array.length === 0) return undefined;
    
    if (keyFunction) {
      return array.reduce((min, current) => 
        keyFunction(current) < keyFunction(min) ? current : min
      );
    }
    
    return Math.min(...array);
  }
}

// 使用示例
const numbers = [1, 2, 2, 3, 4, 4, 5];
console.log(ArrayUtils.unique(numbers)); // [1, 2, 3, 4, 5]

const users = [
  { name: "张三", age: 25, department: "IT" },
  { name: "李四", age: 30, department: "HR" },
  { name: "王五", age: 25, department: "IT" },
  { name: "赵六", age: 35, department: "HR" }
];

const groupedByDepartment = ArrayUtils.groupBy(users, user => user.department);
console.log(groupedByDepartment);

const sortedByAge = ArrayUtils.sortBy(users, "age");
console.log(sortedByAge);

const nestedArray = [1, [2, 3], [4, [5, 6]]];
console.log(ArrayUtils.flatten(nestedArray)); // [1, 2, 3, 4, [5, 6]]
console.log(ArrayUtils.flatten(nestedArray, 2)); // [1, 2, 3, 4, 5, 6]

const shuffled = ArrayUtils.shuffle([1, 2, 3, 4, 5]);
console.log(shuffled);

console.log(ArrayUtils.max([1, 5, 3, 9, 2])); // 9
console.log(ArrayUtils.max(users, user => user.age)); // { name: "赵六", age: 35, department: "HR" }

3. 验证和转换工具

javascript
class Validator {
  // 邮箱验证
  static isEmail(email) {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return emailRegex.test(email);
  }
  
  // 手机号验证
  static isPhoneNumber(phone) {
    const phoneRegex = /^1[3-9]\d{9}$/;
    return phoneRegex.test(phone);
  }
  
  // 身份证验证
  static isIdCard(idCard) {
    const idCardRegex = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
    return idCardRegex.test(idCard);
  }
  
  // URL验证
  static isUrl(url) {
    try {
      new URL(url);
      return true;
    } catch {
      return false;
    }
  }
  
  // 数字验证
  static isNumber(value) {
    return !isNaN(parseFloat(value)) && isFinite(value);
  }
  
  // 整数验证
  static isInteger(value) {
    return Number.isInteger(Number(value));
  }
  
  // 数组验证
  static isArray(value) {
    return Array.isArray(value);
  }
  
  // 对象验证
  static isObject(value) {
    return value !== null && typeof value === "object" && !Array.isArray(value);
  }
  
  // 空值验证
  static isEmpty(value) {
    if (value === null || value === undefined) return true;
    if (typeof value === "string") return value.trim().length === 0;
    if (Array.isArray(value)) return value.length === 0;
    if (typeof value === "object") return Object.keys(value).length === 0;
    return false;
  }
}

class Converter {
  // 字节转换为可读格式
  static bytesToSize(bytes) {
    if (bytes === 0) return "0 Bytes";
    
    const k = 1024;
    const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
  }
  
  // 驼峰命名转换为短横线命名
  static camelToKebab(str) {
    return str.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`);
  }
  
  // 短横线命名转换为驼峰命名
  static kebabToCamel(str) {
    return str.replace(/-([a-z])/g, match => match[1].toUpperCase());
  }
  
  // 首字母大写
  static capitalize(str) {
    if (!str) return str;
    return str.charAt(0).toUpperCase() + str.slice(1);
  }
  
  // 金额格式化
  static formatCurrency(amount, currency = "CNY") {
    return new Intl.NumberFormat("zh-CN", {
      style: "currency",
      currency: currency
    }).format(amount);
  }
  
  // 日期格式化
  static formatDate(date, locale = "zh-CN") {
    return new Intl.DateTimeFormat(locale).format(new Date(date));
  }
  
  // 数字格式化
  static formatNumber(number, options = {}) {
    return new Intl.NumberFormat("zh-CN", options).format(number);
  }
}

// 使用示例
console.log(Validator.isEmail("test@example.com")); // true
console.log(Validator.isPhoneNumber("13812345678")); // true
console.log(Validator.isIdCard("110101199001011234")); // true
console.log(Validator.isUrl("https://example.com")); // true
console.log(Validator.isNumber("123.45")); // true
console.log(Validator.isInteger("123")); // true
console.log(Validator.isArray([1, 2, 3])); // true
console.log(Validator.isObject({ a: 1 })); // true
console.log(Validator.isEmpty("")); // true
console.log(Validator.isEmpty([])); // true
console.log(Validator.isEmpty({})); // true

console.log(Converter.bytesToSize(1024)); // "1 KB"
console.log(Converter.bytesToSize(1048576)); // "1 MB"
console.log(Converter.camelToKebab("userName")); // "user-name"
console.log(Converter.kebabToCamel("user-name")); // "userName"
console.log(Converter.capitalize("hello")); // "Hello"
console.log(Converter.formatCurrency(1234.56)); // "¥1,234.56"
console.log(Converter.formatDate("2024-01-15")); // "2024/1/15"
console.log(Converter.formatNumber(1234.567, { maximumFractionDigits: 2 })); // "1,234.57"

实际应用示例

1. HTTP 客户端工具

javascript
class HttpClient {
  // 静态属性存储默认配置
  static defaults = {
    baseURL: "",
    timeout: 5000,
    headers: {
      "Content-Type": "application/json"
    }
  };
  
  // 静态方法创建实例
  static create(config = {}) {
    const client = new HttpClient();
    client.config = { ...this.defaults, ...config };
    return client;
  }
  
  // 静态方法执行 GET 请求
  static async get(url, config = {}) {
    return this.#request("GET", url, null, config);
  }
  
  // 静态方法执行 POST 请求
  static async post(url, data, config = {}) {
    return this.#request("POST", url, data, config);
  }
  
  // 静态方法执行 PUT 请求
  static async put(url, data, config = {}) {
    return this.#request("PUT", url, data, config);
  }
  
  // 静态方法执行 DELETE 请求
  static async delete(url, config = {}) {
    return this.#request("DELETE", url, null, config);
  }
  
  // 私有静态方法执行请求
  static async #request(method, url, data, config) {
    const finalConfig = { ...this.defaults, ...config };
    const fullUrl = finalConfig.baseURL + url;
    
    const options = {
      method: method,
      headers: finalConfig.headers,
      timeout: finalConfig.timeout
    };
    
    if (data && (method === "POST" || method === "PUT")) {
      options.body = JSON.stringify(data);
    }
    
    try {
      const response = await this.#fetchWithTimeout(fullUrl, options, finalConfig.timeout);
      
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }
      
      const contentType = response.headers.get("content-type");
      if (contentType && contentType.includes("application/json")) {
        return await response.json();
      }
      
      return await response.text();
    } catch (error) {
      throw new Error(`请求失败: ${error.message}`);
    }
  }
  
  // 带超时的 fetch
  static async #fetchWithTimeout(url, options, timeout) {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeout);
    
    try {
      const response = await fetch(url, {
        ...options,
        signal: controller.signal
      });
      clearTimeout(timeoutId);
      return response;
    } catch (error) {
      clearTimeout(timeoutId);
      if (error.name === "AbortError") {
        throw new Error("请求超时");
      }
      throw error;
    }
  }
  
  // 静态方法设置默认配置
  static setDefaults(config) {
    this.defaults = { ...this.defaults, ...config };
  }
  
  // 静态方法添加请求拦截器
  static addRequestInterceptor(interceptor) {
    if (!this.requestInterceptors) {
      this.requestInterceptors = [];
    }
    this.requestInterceptors.push(interceptor);
  }
  
  // 静态方法添加响应拦截器
  static addResponseInterceptor(interceptor) {
    if (!this.responseInterceptors) {
      this.responseInterceptors = [];
    }
    this.responseInterceptors.push(interceptor);
  }
  
  // 静态方法处理请求拦截
  static async #handleRequest(config) {
    if (this.requestInterceptors) {
      for (const interceptor of this.requestInterceptors) {
        config = await interceptor(config);
      }
    }
    return config;
  }
  
  // 静态方法处理响应拦截
  static async #handleResponse(response) {
    if (this.responseInterceptors) {
      for (const interceptor of this.responseInterceptors) {
        response = await interceptor(response);
      }
    }
    return response;
  }
}

// 使用示例
// 设置默认配置
HttpClient.setDefaults({
  baseURL: "https://api.example.com",
  timeout: 10000
});

// 添加请求拦截器
HttpClient.addRequestInterceptor(async (config) => {
  console.log("发送请求:", config);
  // 可以添加认证 token 等
  return config;
});

// 添加响应拦截器
HttpClient.addResponseInterceptor(async (response) => {
  console.log("收到响应:", response.status);
  return response;
});

// 执行请求
// HttpClient.get("/users")
//   .then(data => console.log(data))
//   .catch(error => console.error(error));

// HttpClient.post("/users", { name: "张三", email: "zhangsan@example.com" })
//   .then(data => console.log(data))
//   .catch(error => console.error(error));

console.log("HTTP 客户端工具示例创建完成");

2. 缓存管理器

javascript
class CacheManager {
  // 静态属性存储缓存数据
  static #cache = new Map();
  static #timers = new Map();
  
  // 静态方法设置缓存
  static set(key, value, ttl = 0) {
    // 清除已存在的定时器
    if (this.#timers.has(key)) {
      clearTimeout(this.#timers.get(key));
      this.#timers.delete(key);
    }
    
    // 设置缓存
    this.#cache.set(key, {
      value: value,
      createdAt: Date.now()
    });
    
    // 设置过期时间
    if (ttl > 0) {
      const timer = setTimeout(() => {
        this.delete(key);
      }, ttl);
      
      this.#timers.set(key, timer);
    }
    
    return true;
  }
  
  // 静态方法获取缓存
  static get(key) {
    if (!this.#cache.has(key)) {
      return undefined;
    }
    
    return this.#cache.get(key).value;
  }
  
  // 静态方法检查缓存是否存在
  static has(key) {
    return this.#cache.has(key);
  }
  
  // 静态方法删除缓存
  static delete(key) {
    if (this.#timers.has(key)) {
      clearTimeout(this.#timers.get(key));
      this.#timers.delete(key);
    }
    
    return this.#cache.delete(key);
  }
  
  // 静态方法清空所有缓存
  static clear() {
    // 清除所有定时器
    for (const timer of this.#timers.values()) {
      clearTimeout(timer);
    }
    
    this.#timers.clear();
    this.#cache.clear();
    
    return true;
  }
  
  // 静态方法获取缓存信息
  static getInfo(key) {
    if (!this.#cache.has(key)) {
      return null;
    }
    
    const cacheItem = this.#cache.get(key);
    return {
      key: key,
      value: cacheItem.value,
      createdAt: cacheItem.createdAt,
      age: Date.now() - cacheItem.createdAt
    };
  }
  
  // 静态方法获取所有缓存键
  static keys() {
    return Array.from(this.#cache.keys());
  }
  
  // 静态方法获取缓存大小
  static size() {
    return this.#cache.size;
  }
  
  // 静态方法批量设置缓存
  static setBatch(items, ttl = 0) {
    Object.entries(items).forEach(([key, value]) => {
      this.set(key, value, ttl);
    });
    
    return true;
  }
  
  // 静态方法批量获取缓存
  static getBatch(keys) {
    const result = {};
    keys.forEach(key => {
      result[key] = this.get(key);
    });
    return result;
  }
  
  // 静态方法设置带标签的缓存
  static setWithTag(key, value, tag, ttl = 0) {
    this.set(key, value, ttl);
    
    // 存储标签信息
    if (!this.#tags) {
      this.#tags = new Map();
    }
    
    if (!this.#tags.has(tag)) {
      this.#tags.set(tag, new Set());
    }
    
    this.#tags.get(tag).add(key);
    
    return true;
  }
  
  // 静态方法根据标签清除缓存
  static clearByTag(tag) {
    if (!this.#tags || !this.#tags.has(tag)) {
      return false;
    }
    
    const keys = this.#tags.get(tag);
    keys.forEach(key => {
      this.delete(key);
    });
    
    this.#tags.delete(tag);
    
    return true;
  }
  
  // 静态方法导出缓存
  static export() {
    const exported = {};
    
    for (const [key, cacheItem] of this.#cache) {
      exported[key] = {
        value: cacheItem.value,
        createdAt: cacheItem.createdAt
      };
    }
    
    return JSON.stringify(exported);
  }
  
  // 静态方法导入缓存
  static import(cacheString) {
    try {
      const imported = JSON.parse(cacheString);
      
      Object.entries(imported).forEach(([key, cacheItem]) => {
        this.#cache.set(key, {
          value: cacheItem.value,
          createdAt: cacheItem.createdAt
        });
      });
      
      return true;
    } catch (error) {
      console.error("导入缓存失败:", error);
      return false;
    }
  }
}

// 使用示例
CacheManager.set("user:1", { name: "张三", age: 25 }, 5000); // 5秒过期
CacheManager.set("user:2", { name: "李四", age: 30 });

console.log(CacheManager.get("user:1")); // { name: "张三", age: 25 }
console.log(CacheManager.has("user:1")); // true
console.log(CacheManager.getInfo("user:1"));

// 批量操作
CacheManager.setBatch({
  "config:api": "https://api.example.com",
  "config:timeout": 5000
}, 10000); // 10秒过期

console.log(CacheManager.getBatch(["config:api", "config:timeout"]));

// 标签操作
CacheManager.setWithTag("session:1", "session_data_1", "sessions", 30000);
CacheManager.setWithTag("session:2", "session_data_2", "sessions", 30000);

console.log("缓存大小:", CacheManager.size());
console.log("缓存键:", CacheManager.keys());

// 3秒后检查过期缓存
setTimeout(() => {
  console.log("user:1 是否存在:", CacheManager.has("user:1")); // false
}, 3000);

// 导出和导入
const exportedCache = CacheManager.export();
console.log("导出的缓存:", exportedCache);

CacheManager.clear();
console.log("清空后缓存大小:", CacheManager.size()); // 0

CacheManager.import(exportedCache);
console.log("导入后缓存大小:", CacheManager.size()); // 3

总结

JavaScript 静态方法的核心要点:

  1. 定义方式:使用 static 关键字定义静态方法
  2. 调用方式:通过类名直接调用,不能通过实例调用
  3. 访问限制:不能访问实例属性,可以访问静态属性和方法
  4. 应用场景:工具类方法、工厂方法、配置管理、单例模式等
  5. 继承特性:子类可以继承父类的静态方法
  6. 最佳实践:合理使用静态方法,避免滥用

静态方法是 JavaScript 类的重要特性,掌握它们的使用能够让你编写出更加优雅和高效的代码。在下一章节中,我们将学习 JavaScript 的数组。

本站内容仅供学习和研究使用。