JavaScript 实用封装技巧

JavaScript 实用封装技巧


1. 工厂封装

如果需要创建多个结构相似的对象,可以使用工厂函数。

// 创建书籍的工厂函数
function createBook(title, author) {
  return {
    title: title,
    author: author,
    getDetails() {
      return `《${this.title}》- 作者: ${this.author}`;
    },
  };
}

const book1 = createBook("JavaScript 权威指南", "Flanagan");
const book2 = createBook("你不知道的 JavaScript", "Kyle Simpson");

console.log(book1.getDetails()); // 输出: 《JavaScript 权威指南》- 作者: Flanagan

2. 闭包封装

有时候,我们不希望外部直接修改对象内部的数据,这时可以利用闭包将状态"藏"起来。

// 封装一个计数器
function createCounter() {
  let count = 0; // 私有变量,外部无法直接访问

  return {
    increment() {
      count++;
      console.log(`当前计数: ${count}`);
    },
    decrement() {
      count--;
      console.log(`当前计数: ${count}`);
    },
    getCount() {
      return count;
    },
  };
}

const myCounter = createCounter();
myCounter.increment(); // 当前计数: 1
// console.log(myCounter.count); // undefined (无法直接访问)

3. Class 类封装

传统oop方式,更符合面向对象编程习惯。

class Car {
  constructor(brand, model) {
    this.brand = brand;
    this.model = model;
    this.speed = 0;
  }

  // 封装加速行为
  accelerate(value) {
    this.speed += value;
    console.log(
      `${this.brand} ${this.model} 正在加速,当前时速: ${this.speed}km/h`,
    );
  }

  // 封装刹车行为
  brake() {
    this.speed = 0;
    console.log("车辆已停止。");
  }
}

const myCar = new Car("特斯拉", "Model 3");
myCar.accelerate(50);
myCar.brake();

4. 高阶函数(逻辑委托)

高阶函数是指接收函数作为参数,或者将函数作为返回值的函数。这种封装技巧可以让逻辑变得灵活,适合固定通用逻辑,隔离差异逻辑。

4.1 基础列表处理

// 封装一个通用的列表处理器
function processList(list, callback) {
  const result = [];
  for (let i = 0; i < list.length; i++) {
    result.push(callback(list[i]));
  }
  return result;
}

const numbers = [1, 2, 3, 4];
const doubled = processList(numbers, (num) => {
  return num * 2
});
console.log(doubled); // [2, 4, 6, 8]

4.2 异步请求封装 (Fetch)

/**
 * 封装通用的数据获取函数
 * @param {string} url 请求地址
 * @param {function} handleData 处理数据的回调函数
 */
async function fetchData(url, handleData) {
  try {
    console.log("正在请求数据...");
    const response = await fetch(url);
    const data = await response.json();
    
    // 封装技巧:不在这里写死处理逻辑,而是调用传入的回调函数
    handleData(data);
    
  } catch (error) {
    console.error("请求出错:", error);
  }
}

// 使用场景 1:打印用户信息
fetchData("https://api.example.com/user", (user) => {
  console.log(`获取到用户: ${user.name}`);
});

// 使用场景 2:只提取用户的 ID 列表
fetchData("https://api.example.com/users", (users) => {
  const ids = users.map(u => u.id);
  console.log("用户 ID 列表:", ids);
});

5. 函数柯里化(预设参数)

将一个多参数函数转换成一系列单参数函数,用来“固定”某些参数。

// 封装一个通用的日志打印器
const createLogger = (type) => (message) => {
  console.log(`[${type}] ${new Date().toLocaleTimeString()}: ${message}`);
};

// 预设好“错误”类型的打印器
const logError = createLogger("错误");
const logInfo = createLogger("信息");

logInfo("系统启动成功"); // 输出: [信息] 14:30:05: 系统启动成功
logError("数据库连接失败"); // 输出: [错误] 14:30:10: 数据库连接失败

6. 函数组合

将小函数组合成大函数,每个函数只负责一小块逻辑。

const addExclamation = (str) => `${str}!`;
const toUpper = (str) => str.toUpperCase();

// 简单版本
const formatShout = (str) => addExclamation(toUpper(str));

// 复杂版本
const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x);
const formatShout = compose(addExclamation, toUpper);

console.log(formatShout("hello")); // HELLO!

7. 深/浅拷贝(知识补充)

7.1 浅拷贝

只能复制对象的第一层属性,嵌套对象仍然是引用

const obj1 = { a: 1, b: 2 }

// 方式1
const obj2 = { ...obj1 }

// 方式2
Object.assign({}, obj1)

7.2 深拷贝

能复制深层属性,嵌套对象不受影响,各自独立

const obj1 = { a: 1, b: { c: 2 } };

// 方式1(性能一般,无兼容性)
const obj2 = JSON.parse(JSON.stringify(obj1));

// 方式2(性能好,Chrome 97+ 版本支持)
const obj2 = structuredClone(obj);
posted @ 2026-03-19 21:10  戡玉  阅读(28)  评论(0)    收藏  举报