1. 常用函数合集概述
在日常开发工作中,我们经常会遇到一些重复性的功能需求。与其每次都从头编写代码,不如将这些常用功能封装成可复用的函数。这个常用函数合集就是我在多年开发实践中积累的一套工具函数库,涵盖了字符串处理、数组操作、日期格式化、数据验证等高频使用场景。
这些函数经过多个项目的实战检验,具有以下特点:
- 功能独立:每个函数只做一件事
- 兼容性强:支持主流浏览器和Node.js环境
- 性能优化:避免常见性能陷阱
- 类型安全:提供TypeScript类型定义
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心功能分类与实现
2.1 字符串处理函数
字符串操作是开发中最常见的需求之一。以下是几个高频使用的字符串处理函数:
javascript复制/**
* 去除字符串首尾空格(兼容IE)
* @param {string} str
* @returns {string}
*/
function trim(str) {
return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
}
/**
* 将字符串转为驼峰命名
* @param {string} str
* @returns {string}
*/
function camelCase(str) {
return str.replace(/[-_\s]+(.)?/g, (_, c) =>
c ? c.toUpperCase() : ''
);
}
/**
* 生成随机字符串
* @param {number} len 长度
* @param {string} type 类型:number/letter/all
* @returns {string}
*/
function randomString(len = 16, type = 'all') {
const numbers = '0123456789';
const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
const chars = {
number: numbers,
letter: letters,
all: numbers + letters
}[type] || chars.all;
let result = '';
for (let i = 0; i < len; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
注意事项:
- trim函数考虑了IE浏览器不兼容原生trim方法的情况
- camelCase函数能处理连字符、下划线和空格多种分隔符
- randomString提供了三种随机字符串生成模式
2.2 数组操作函数
数组操作是业务逻辑中的另一大常见需求:
javascript复制/**
* 数组去重
* @param {Array} arr
* @returns {Array}
*/
function unique(arr) {
return [...new Set(arr)];
}
/**
* 数组分组
* @param {Array} arr
* @param {number} size 每组大小
* @returns {Array}
*/
function chunk(arr, size = 1) {
const result = [];
for (let i = 0; i < arr.length; i += size) {
result.push(arr.slice(i, i + size));
}
return result;
}
/**
* 根据条件过滤数组中的假值
* @param {Array} arr
* @param {Function} predicate 过滤函数
* @returns {Array}
*/
function compact(arr, predicate = Boolean) {
return arr.filter(predicate);
}
实际应用场景:
- unique常用于去除重复ID列表
- chunk在处理分页或批量操作时非常有用
- compact可以快速过滤掉数组中的null/undefined等值
2.3 日期时间处理
日期处理是业务开发中的痛点之一,以下函数可以简化常见操作:
javascript复制/**
* 格式化日期
* @param {Date|string|number} date
* @param {string} format 格式,如'YYYY-MM-DD'
* @returns {string}
*/
function formatDate(date, format = 'YYYY-MM-DD') {
const d = new Date(date);
const pad = n => n.toString().padStart(2, '0');
return format
.replace(/YYYY/g, d.getFullYear())
.replace(/MM/g, pad(d.getMonth() + 1))
.replace(/DD/g, pad(d.getDate()))
.replace(/HH/g, pad(d.getHours()))
.replace(/mm/g, pad(d.getMinutes()))
.replace(/ss/g, pad(d.getSeconds()));
}
/**
* 计算日期差
* @param {Date} date1
* @param {Date} date2
* @param {string} unit 单位:day/hour/minute/second
* @returns {number}
*/
function dateDiff(date1, date2, unit = 'day') {
const diff = date1.getTime() - date2.getTime();
const units = {
day: 1000 * 60 * 60 * 24,
hour: 1000 * 60 * 60,
minute: 1000 * 60,
second: 1000
};
return Math.floor(diff / units[unit]);
}
/**
* 获取当天的开始时间
* @param {Date} date
* @returns {Date}
*/
function startOfDay(date) {
const d = new Date(date);
d.setHours(0, 0, 0, 0);
return d;
}
经验分享:
- formatDate函数比引入整个moment.js库更轻量
- dateDiff计算两个日期的差值,支持多种时间单位
- startOfDay在需要按天统计数据时特别有用
3. 数据验证与类型判断
3.1 常用验证函数
javascript复制/**
* 验证手机号格式
* @param {string} phone
* @returns {boolean}
*/
function isPhone(phone) {
return /^1[3-9]\d{9}$/.test(phone);
}
/**
* 验证邮箱格式
* @param {string} email
* @returns {boolean}
*/
function isEmail(email) {
return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email);
}
/**
* 验证身份证号
* @param {string} idCard
* @returns {boolean}
*/
function isIdCard(idCard) {
// 简化的验证逻辑,实际项目需要更完整的验证
return /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/.test(idCard);
}
3.2 类型判断函数
javascript复制/**
* 判断是否为对象
* @param {any} obj
* @returns {boolean}
*/
function isObject(obj) {
return obj !== null && typeof obj === 'object' && !Array.isArray(obj);
}
/**
* 判断是否为Promise
* @param {any} obj
* @returns {boolean}
*/
function isPromise(obj) {
return !!obj && (typeof obj === 'object' || typeof obj === 'function')
&& typeof obj.then === 'function';
}
/**
* 判断是否为函数
* @param {any} fn
* @returns {boolean}
*/
function isFunction(fn) {
return typeof fn === 'function';
}
4. 浏览器与DOM操作
4.1 常用DOM操作
javascript复制/**
* 获取元素计算样式
* @param {HTMLElement} el
* @param {string} prop
* @returns {string}
*/
function getStyle(el, prop) {
return window.getComputedStyle
? window.getComputedStyle(el, null)[prop]
: el.currentStyle[prop];
}
/**
* 元素是否包含指定类名
* @param {HTMLElement} el
* @param {string} className
* @returns {boolean}
*/
function hasClass(el, className) {
return el.classList
? el.classList.contains(className)
: new RegExp('(^|\\s)' + className + '(\\s|$)').test(el.className);
}
/**
* 添加类名
* @param {HTMLElement} el
* @param {string} className
*/
function addClass(el, className) {
if (el.classList) {
el.classList.add(className);
} else if (!hasClass(el, className)) {
el.className += ' ' + className;
}
}
4.2 浏览器相关函数
javascript复制/**
* 获取URL参数
* @param {string} name
* @returns {string|null}
*/
function getQueryParam(name) {
const params = new URLSearchParams(window.location.search);
return params.get(name);
}
/**
* 设置Cookie
* @param {string} name
* @param {string} value
* @param {number} days 过期天数
*/
function setCookie(name, value, days = 7) {
const date = new Date();
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
document.cookie = `${name}=${encodeURIComponent(value)};expires=${date.toUTCString()};path=/`;
}
/**
* 滚动到页面顶部
* @param {number} duration 滚动时长(ms)
*/
function scrollToTop(duration = 300) {
const start = window.pageYOffset;
const startTime = performance.now();
function scroll() {
const now = performance.now();
const time = Math.min(1, (now - startTime) / duration);
window.scrollTo(0, start * (1 - easeInOutCubic(time)));
if (time < 1) {
requestAnimationFrame(scroll);
}
}
function easeInOutCubic(t) {
return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
}
requestAnimationFrame(scroll);
}
5. 性能优化与高级技巧
5.1 节流与防抖
javascript复制/**
* 函数防抖
* @param {Function} fn
* @param {number} delay
* @returns {Function}
*/
function debounce(fn, delay = 300) {
let timer = null;
return function(...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
timer = null;
}, delay);
};
}
/**
* 函数节流
* @param {Function} fn
* @param {number} interval
* @returns {Function}
*/
function throttle(fn, interval = 300) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastTime >= interval) {
fn.apply(this, args);
lastTime = now;
}
};
}
5.2 深拷贝实现
javascript复制/**
* 深拷贝
* @param {any} obj
* @returns {any}
*/
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
if (obj instanceof Date) {
return new Date(obj.getTime());
}
if (obj instanceof RegExp) {
return new RegExp(obj);
}
if (Array.isArray(obj)) {
return obj.map(item => deepClone(item));
}
const result = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = deepClone(obj[key]);
}
}
return result;
}
6. 实用工具函数
6.1 数据转换
javascript复制/**
* 对象转URL参数字符串
* @param {Object} obj
* @returns {string}
*/
function objectToQueryString(obj) {
return Object.keys(obj)
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`)
.join('&');
}
/**
* URL参数字符串转对象
* @param {string} queryString
* @returns {Object}
*/
function queryStringToObject(queryString) {
return Object.fromEntries(new URLSearchParams(queryString));
}
6.2 其他实用函数
javascript复制/**
* 生成UUID
* @returns {string}
*/
function generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
/**
* 异步加载脚本
* @param {string} url
* @returns {Promise}
*/
function loadScript(url) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = url;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
}
7. 函数合集的维护与扩展
7.1 如何组织这些函数
在实际项目中,我通常将这些函数按功能模块组织在不同的文件中:
code复制utils/
├── string.js # 字符串相关函数
├── array.js # 数组相关函数
├── date.js # 日期相关函数
├── validate.js # 验证相关函数
├── dom.js # DOM操作函数
└── index.js # 统一导出入口
然后在index.js中统一导出:
javascript复制export * from './string';
export * from './array';
export * from './date';
export * from './validate';
export * from './dom';
7.2 添加新函数的准则
当需要添加新函数时,我会遵循以下原则:
- 解决具体问题:每个函数应该解决一个明确的问题
- 保持简洁:函数应该尽可能简单,避免过度设计
- 良好注释:使用JSDoc格式注释说明函数用途和参数
- 单元测试:为重要函数编写单元测试
- 性能考虑:避免潜在的性能问题
7.3 版本管理与更新
建议使用Git进行版本管理,遵循语义化版本控制:
- 补丁版本(1.0.x):修复bug但不影响API
- 小版本(1.x.0):向后兼容的功能新增
- 大版本(x.0.0):不兼容的API修改
8. 常见问题与解决方案
8.1 函数兼容性问题
问题:某些函数在旧版浏览器中可能无法工作
解决方案:
- 使用Babel等工具转译代码
- 为旧浏览器提供polyfill
- 在函数内部做兼容性判断
8.2 性能优化建议
- 避免在循环中创建函数
- 缓存频繁访问的DOM元素
- 使用事件委托减少事件监听器数量
- 对大数组操作考虑使用Web Worker
8.3 调试技巧
- 使用console.time和console.timeEnd测量函数执行时间
- 为复杂函数添加debugger语句
- 使用try-catch捕获可能的错误
- 编写单元测试验证边界条件
这套常用函数合集已经在我参与的多
