JavaScript 工具函数简介 #

什么是工具函数? #

工具函数(Utility Functions)是一类专门用于解决特定问题的、可复用的代码片段。它们通常具有以下特点:

text
┌─────────────────────────────────────────────────────────────┐
│                     工具函数特点                              │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │  单一职责    │  │  无副作用    │  │  可测试     │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │  高复用      │  │  易维护      │  │  可组合     │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
└─────────────────────────────────────────────────────────────┘

工具函数的定义 #

javascript
function formatDate(date) {
    const d = new Date(date);
    const year = d.getFullYear();
    const month = String(d.getMonth() + 1).padStart(2, '0');
    const day = String(d.getDate()).padStart(2, '0');
    return `${year}-${month}-${day}`;
}

formatDate(new Date());

为什么需要工具函数? #

开发中的常见问题 #

text
问题场景:

1. 重复代码
   ┌─────────────────────────────────────────┐
   │  文件A: 日期格式化代码                   │
   │  文件B: 相同的日期格式化代码             │
   │  文件C: 又是相同的日期格式化代码         │
   └─────────────────────────────────────────┘
   问题:修改时需要改多处,容易遗漏

2. 代码质量参差不齐
   ┌─────────────────────────────────────────┐
   │  开发者A: 实现方式1                      │
   │  开发者B: 实现方式2                      │
   │  开发者C: 实现方式3                      │
   └─────────────────────────────────────────┘
   问题:风格不统一,维护困难

3. 边界条件处理不足
   ┌─────────────────────────────────────────┐
   │  正常情况: 正常工作                      │
   │  边界情况: 报错或异常                    │
   └─────────────────────────────────────────┘
   问题:Bug 频发,稳定性差

工具函数的解决方案 #

javascript
import { formater } from './utils/date';

const date1 = formater(Date.now(), 'yyyy-MM-dd');
const date2 = formater('2026-04-04', 'yyyy/MM/dd');
const date3 = formater(new Date(), 'MM-dd HH:mm');

工具函数的分类 #

1. 数据处理类 #

javascript
export const deepCopy = (obj, map = new WeakMap()) => {
    if (typeof obj !== 'object' || obj === null) {
        return obj;
    }
    if (map.has(obj)) {
        return map.get(obj);
    }
    const clone = Array.isArray(obj) ? [] : {};
    map.set(obj, clone);
    for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
            clone[key] = deepCopy(obj[key], map);
        }
    }
    return clone;
};

2. 字符串处理类 #

javascript
export const getCharLength = (str) => {
    let length = 0;
    for (let i = 0; i < str.length; i++) {
        const charCode = str.charCodeAt(i);
        length += (charCode >= 0x4E00 && charCode <= 0x9FFF) ? 2 : 1;
    }
    return length;
};

getCharLength('Hello世界');

3. 日期时间类 #

javascript
export const formater = (time, format = '') => {
    const timeInfo = getTimeInfo(time);
    if (!timeInfo) return '';
    const { yyyy, MM, dd, hh, mm, ss, HH } = timeInfo;
    return format
        .replace(/yyyy/, yyyy)
        .replace(/MM/, MM)
        .replace(/dd/, dd)
        .replace(/HH/, HH)
        .replace(/hh/, hh)
        .replace(/mm/, mm)
        .replace(/ss/, ss);
};

4. 网络请求类 #

javascript
export const getQueryString = (name) => {
    const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
    const r = window.location.search.slice(1).match(reg);
    if (r != null) {
        return decodeURIComponent(r[2]);
    }
    return '';
};

5. 存储操作类 #

javascript
const store = {
    get(key) {
        const value = localStorage.getItem(key);
        try {
            const parsed = JSON.parse(value) || {};
            const { expires = '', data = null } = parsed;
            if (expires && new Date(expires) < new Date()) {
                store.remove(key);
                return null;
            }
            return data;
        } catch {
            return null;
        }
    },
    set(key, value, expires) {
        localStorage.setItem(key, JSON.stringify({
            expires,
            data: value
        }));
    },
    remove(key) {
        localStorage.removeItem(key);
    }
};

工具函数的设计原则 #

1. 单一职责原则 #

javascript
function formatDate(date) {
    return formater(date, 'yyyy-MM-dd');
}

function formatTime(date) {
    return formater(date, 'HH:mm:ss');
}

function formatDateTime(date) {
    return formater(date, 'yyyy-MM-dd HH:mm:ss');
}

2. 纯函数原则 #

javascript
const add = (a, b) => a + b;

add(1, 2);
add(1, 2);
add(1, 2);

3. 防御性编程 #

javascript
export const getCookie = (name) => {
    if (!name) return null;
    try {
        const reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)');
        const match = document.cookie.match(reg);
        return match ? decodeURIComponent(match[2]) : null;
    } catch (e) {
        console.error('Cookie 读取失败:', e);
        return null;
    }
};

4. 可配置性 #

javascript
export const formatFileSize = (size, options = {}) => {
    const {
        precision = 2,
        units = ['B', 'KB', 'MB', 'GB', 'TB']
    } = options;
    
    let filesize = size;
    let i = 0;
    
    while (filesize >= 1024 && i < units.length - 1) {
        filesize /= 1024;
        i++;
    }
    
    return `${filesize.toFixed(precision)}${units[i]}`;
};

formatFileSize(1024);
formatFileSize(1024 * 1024, { precision: 3 });

工具函数 vs 第三方库 #

对比分析 #

特性 自定义工具函数 Lodash Underscore Ramda
体积 极小(按需) ~70KB ~20KB ~45KB
定制性 极高 中等 中等
学习成本 中等
功能丰富度 按需开发 非常丰富 丰富 丰富
函数式编程 支持 支持 支持 强调
Tree-shaking 完美支持 支持 一般 支持

选择建议 #

text
选择自定义工具函数:
├── 项目体积敏感
├── 需求明确且有限
├── 需要高度定制
└── 团队有维护能力

选择第三方库:
├── 项目复杂度高
├── 需要大量工具函数
├── 快速开发优先
└── 团队熟悉该库

工具函数的应用场景 #

1. 表单验证 #

javascript
export const validators = {
    required: (value) => !!value || '此项为必填',
    email: (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) || '邮箱格式不正确',
    phone: (value) => /^1[3-9]\d{9}$/.test(value) || '手机号格式不正确',
    minLength: (min) => (value) => value.length >= min || `最少${min}个字符`,
    maxLength: (max) => (value) => value.length <= max || `最多${max}个字符`
};

validators.email('test@example.com');
validators.phone('13800138000');

2. 数据转换 #

javascript
export const rgb2hex = (rgb = []) => {
    return '#' + rgb.map(item => {
        let value = item.toString(16);
        return value.length === 1 ? `0${value}` : value;
    }).join('');
};

export const hex2rgb = (hex) => {
    let _hex = hex[0] === '#' ? hex.slice(1) : hex;
    const [a, b, c, d, e, f] = _hex.split('');
    return [parseInt(a + b, 16), parseInt(c + d, 16), parseInt(e + f, 16)];
};

rgb2hex([255, 128, 0]);
hex2rgb('#ff8000');

3. 设备检测 #

javascript
export const isMobileAgent = () => {
    const userAgent = navigator.userAgent;
    const reg = /iphone|ipod|ipad|android|mobile/;
    return reg.test(userAgent.toLowerCase());
};

export const getDeviceInfo = () => {
    const ua = navigator.userAgent;
    return {
        isMobile: /mobile/i.test(ua),
        isIOS: /iphone|ipad/i.test(ua),
        isAndroid: /android/i.test(ua),
        isWeChat: /micromessenger/i.test(ua)
    };
};

工具函数的组织方式 #

1. 按功能模块组织 #

text
utils/
├── url.js        # URL 处理
├── cookie.js     # Cookie 操作
├── date.js       # 日期时间
├── store.js      # 本地存储
├── file.js       # 文件处理
├── color.js      # 颜色转换
├── theme.js      # 主题管理
├── crypto.js     # 加密哈希
└── index.js      # 统一导出

2. 统一导出 #

javascript
export { getQueryString, getQueryParam, addQueryParam } from './url';
export { getCookie, setCookie, deleteCookie } from './cookie';
export { formater, getTimeSpan, getTimeInfo } from './date';
export { default as store } from './store';
export { formatFileSize, downloadFile, getImageBase64 } from './file';
export { rgb2hex, hex2rgb } from './color';
export { getTheme, setTheme, toggleTheme } from './theme';
export { default as md5 } from './md5';
export { default as md6 } from './md6';
export { deepCopy, deepMerge } from './index';

下一步 #

现在你已经了解了工具函数的基本概念,接下来学习 基础使用,开始使用这些实用的工具函数!

最后更新:2026-04-04