济南市护送服务网

JavaScript编程中如何进行函数封装

2026-03-31 06:14:02 浏览次数:1
详细信息

一、基础函数封装

1. 基本函数定义

// 函数声明
function calculateArea(width, height) {
    return width * height;
}

// 函数表达式
const calculateArea = function(width, height) {
    return width * height;
};

// 箭头函数(ES6+)
const calculateArea = (width, height) => width * height;

2. 参数处理

// 默认参数
function greet(name = 'Guest', greeting = 'Hello') {
    return `${greeting}, ${name}!`;
}

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

// 解构参数
function printUser({name, age, email}) {
    console.log(`Name: ${name}, Age: ${age}, Email: ${email}`);
}

二、高级封装模式

1. 模块模式

// 立即执行函数表达式(IIFE)
const Calculator = (function() {
    // 私有变量
    let memory = 0;

    // 私有函数
    function validateNumber(num) {
        return typeof num === 'number' && !isNaN(num);
    }

    // 公共API
    return {
        add: function(a, b) {
            if (!validateNumber(a) || !validateNumber(b)) {
                throw new Error('Invalid numbers');
            }
            return a + b;
        },

        storeInMemory: function(value) {
            memory = value;
        },

        getMemory: function() {
            return memory;
        }
    };
})();

2. 工厂函数

function createUser(name, email) {
    // 私有变量
    let loginCount = 0;

    // 返回对象
    return {
        name,
        email,

        login() {
            loginCount++;
            console.log(`${this.name} logged in ${loginCount} times`);
            return this;
        },

        getLoginCount() {
            return loginCount;
        }
    };
}

const user = createUser('Alice', 'alice@example.com');

三、ES6+ 类封装

class User {
    // 私有字段(ES2022)
    #password;

    constructor(name, email, password) {
        this.name = name;
        this.email = email;
        this.#password = password;
        this.loginCount = 0;
    }

    // 公共方法
    login(inputPassword) {
        if (this.#validatePassword(inputPassword)) {
            this.loginCount++;
            console.log(`${this.name} logged in successfully`);
            return true;
        }
        return false;
    }

    // 私有方法
    #validatePassword(inputPassword) {
        return inputPassword === this.#password;
    }

    // 静态方法
    static createAdmin(name, email) {
        const admin = new User(name, email, 'admin123');
        admin.isAdmin = true;
        return admin;
    }
}

四、函数封装最佳实践

1. 单一职责原则

// ❌ 不好的做法
function processUser(user) {
    // 验证、保存、发送邮件都在一个函数
    validateUser(user);
    saveToDatabase(user);
    sendWelcomeEmail(user);
}

// ✅ 好的做法
function processUser(user) {
    validateUser(user);
    persistUser(user);
    notifyUser(user);
}

2. 纯函数

// 纯函数:相同输入总是得到相同输出,无副作用
function calculateTotal(items, taxRate) {
    const subtotal = items.reduce((sum, item) => sum + item.price, 0);
    return subtotal * (1 + taxRate);
}

3. 柯里化和函数组合

// 柯里化
const multiply = a => b => a * b;
const double = multiply(2);
console.log(double(5)); // 10

// 函数组合
const compose = (...fns) => x => fns.reduceRight((acc, fn) => fn(acc), x);
const addTax = price => price * 1.1;
const applyDiscount = price => price * 0.9;
const calculateFinalPrice = compose(addTax, applyDiscount);

五、实际封装示例

1. 数据获取函数

async function fetchData(url, options = {}) {
    const defaultOptions = {
        method: 'GET',
        headers: {
            'Content-Type': 'application/json',
        },
        timeout: 5000,
    };

    const config = { ...defaultOptions, ...options };

    try {
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), config.timeout);

        const response = await fetch(url, {
            ...config,
            signal: controller.signal
        });

        clearTimeout(timeoutId);

        if (!response.ok) {
            throw new Error(`HTTP ${response.status}: ${response.statusText}`);
        }

        return await response.json();
    } catch (error) {
        console.error('Fetch error:', error);
        throw error;
    }
}

2. 缓存函数

function memoize(fn) {
    const cache = new Map();

    return function(...args) {
        const key = JSON.stringify(args);

        if (cache.has(key)) {
            console.log('Returning cached result');
            return cache.get(key);
        }

        const result = fn.apply(this, args);
        cache.set(key, result);
        return result;
    };
}

// 使用示例
const expensiveCalculation = memoize(function(n) {
    console.log('Calculating...');
    return n * 2;
});

六、注意事项

避免全局污染:使用模块作用域 错误处理:适当添加try-catch和参数验证 文档化:使用JSDoc注释 测试:为封装的函数编写测试 性能考虑:避免不必要的闭包和内存泄漏

通过良好的函数封装,可以提高代码的可读性、可维护性和可复用性,是现代JavaScript开发的核心技能之一。

相关推荐