在前端领域摸爬滚打了8年,从一个写 if/else
都心惊胆战的小白,到现在能从容应对各种复杂业务的老兵,我发现,真正拉开开发者之间效率差距的,除了经验和对框架的理解外,还有一个常常被忽略的“秘密武器”——一个属于自己的、顺手的工具函数库。
我们总说“Don't Repeat Yourself (DRY)”,但很多时候,我们仍在不同项目中反复编写着同样逻辑的代码,比如:深拷贝、防抖、节流、获取URL参数等等。
今天,我将这8年来沉淀、打磨、筛选出的20个最高频、最实用的JavaScript工具函数分享给你。它们全部是原生JS或ES6+实现,无任何依赖,你可以直接复制到你的项目中使用。
1. 防抖 (Debounce)
场景:防止函数在短时间内被高频触发,常用于输入框搜索、窗口大小调整等。
代码:
function debounce(fn, delay) {
let timer = null;
return function(...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
// 使用示例
const debouncedSearch = debounce(() => console.log('Searching...'), 500);
window.addEventListener('input', debouncedSearch);
2. 节流 (Throttle)
场景:保证函数在一定时间间隔内只执行一次,常用于监听滚动事件、拖拽事件。
代码:
function throttle(fn, delay) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastTime > delay) {
lastTime = now;
fn.apply(this, args);
}
};
}
// 使用示例
const throttledScroll = throttle(() => console.log('Scrolling...'), 1000);
window.addEventListener('scroll', throttledScroll);
3. 深拷贝 (Deep Clone)
场景:完全复制一个对象,包括其嵌套的对象和数组,断开引用关系。
注意: 这是简易版,对于更复杂的场景(如循环引用、特殊对象类型),推荐使用 structuredClone (现代浏览器原生支持) 或 lodash.cloneDeep。
代码:
function deepClone(obj, hash = new WeakMap()) {
if (obj === null || typeof obj !== 'object') return obj;
if (hash.has(obj)) return hash.get(obj);
const cloneObj = Array.isArray(obj) ? [] : {};
hash.set(obj, cloneObj);
for (let key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
cloneObj[key] = deepClone(obj[key], hash);
}
}
return cloneObj;
}
// 使用示例
const obj1 = { a: 1, b: { c: 2 } };
const obj2 = deepClone(obj1);
obj2.b.c = 3;
console.log(obj1.b.c); // 输出 2
4. 数组去重 (Unique Array)
场景:移除数组中的重复元素。
代码:
JavaScript
function uniqueArray(arr) {
return [...new Set(arr)];
}
// 使用示例
console.log(uniqueArray([1, 1, 'a', 'a', 2, 2])); // 输出 [1, "a", 2]
5. 数组扁平化 (Flatten Array)
场景:将多维数组转化为一维数组。
代码:
function flattenArray(arr) {
return arr.reduce((acc, val) =>
Array.isArray(val) ? acc.concat(flattenArray(val)) : acc.concat(val),
[]);
}
// 或者使用原生方法 (ES2019)
// const flattened = arr.flat(Infinity);
// 使用示例
const nestedArray = [1, [2, [3, [4]], 5]];
console.log(flattenArray(nestedArray)); // 输出 [1, 2, 3, 4, 5]
6. 生成随机字符串 (Generate Random String)
场景:生成一个指定长度的随机字符串,常用作唯一ID。
代码:
function randomString(length = 8) {
return Math.random().toString(36).substring(2, 2 + length);
}
// 使用示例
console.log(randomString(10)); // 输出类似 "7j2k9n4p1q"
7. 首字母大写 (Capitalize)
场景:将字符串的第一个字母转换为大写。
代码:
function capitalize([first, ...rest]) {
return first.toUpperCase() + rest.join('');
}
// 使用示例
console.log(capitalize('helloWorld')); // 输出 "HelloWorld"
8. 检查对象是否为空 (Is Object Empty)
场景:判断一个对象是否没有任何自身属性。
代码:
function isObjectEmpty(obj) {
return obj && Object.keys(obj).length === 0 && obj.constructor === Object;
}
// 使用示例
console.log(isObjectEmpty({})); // true
console.log(isObjectEmpty({ a: 1 })); // false
9. 异步延迟/休眠 (Sleep)
场景:在 async/await
流程中暂停指定的毫秒数。
代码:
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 使用示例
async function doSomething() {
console.log('Start');
await sleep(2000);
console.log('End after 2 seconds');
}
doSomething();
10. 获取URL查询参数 (Get Query Params)
场景:将URL的查询字符串解析成一个对象。
代码:
function getQueryParams(url = window.location.href) {
const searchParams = new URL(url).searchParams;
const params = {};
for (const [key, value] of searchParams.entries()) {
params[key] = value;
}
return params;
}
// 使用示例
// 假设 URL 是 "https://example.com?name=gemini&age=1"
// console.log(getQueryParams()); // 输出 { name: "gemini", age: "1" }
11. 格式化货币 (Format Currency)
场景:将数字格式化为货币字符串。
代码:
function formatCurrency(amount, currency = 'CNY', locale = 'zh-CN') {
return new Intl.NumberFormat(locale, {
style: 'currency',
currency: currency,
}).format(amount);
}
// 使用示例
console.log(formatCurrency(12345.67)); // 输出 "¥12,345.67"
console.log(formatCurrency(12345.67, 'USD', 'en-US')); // 输出 "$12,345.67"
12. 复制到剪贴板 (Copy to Clipboard)
场景:将文本内容异步复制到用户剪贴板。
代码:
async function copyToClipboard(text) {
if (!navigator.clipboard) {
console.error('Clipboard API not available');
return Promise.reject('Clipboard API not available');
}
try {
await navigator.clipboard.writeText(text);
console.log('Copied to clipboard');
return Promise.resolve();
} catch (err) {
console.error('Failed to copy: ', err);
return Promise.reject(err);
}
}
// 使用示例
// copyToClipboard('Hello, Gemini!');
13. 数组分块 (Chunk Array)
场景:将一个大数组按指定大小分割成多个小数组。
代码:
function chunkArray(arr, size) {
const result = [];
for (let i = 0; i < arr.length; i += size) {
result.push(arr.slice(i, i + size));
}
return result;
}
// 使用示例
const numbers = [1, 2, 3, 4, 5, 6, 7, 8];
console.log(chunkArray(numbers, 3)); // 输出 [[1, 2, 3], [4, 5, 6], [7, 8]]
14. 从对象中拾取属性 (Pick)
场景:从一个对象中选择指定的若干个属性,返回一个新对象。
代码:
function pick(obj, ...keys) {
return keys.reduce((acc, key) => {
if (obj && Object.prototype.hasOwnProperty.call(obj, key)) {
acc[key] = obj[key];
}
return acc;
}, {});
}
// 使用示例
const user = { id: 1, name: 'Gemini', age: 1, email: 'gemini@google.com' };
console.log(pick(user, 'id', 'name')); // 输出 { id: 1, name: 'Gemini' }
15. 生成范围内的随机数 (Random in Range)
场景:获取一个介于 min
和 max
之间的随机整数。
代码:
function randomInRange(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// 使用示例
console.log(randomInRange(10, 20)); // 输出 10 到 20 之间的一个整数
16. 判断是否在浏览器环境 (Is Browser)
场景:在编写同构(Isomorphic)代码时,判断当前环境是否为浏览器。
代码:
const isBrowser = () => typeof window !== 'undefined' && typeof window.document !== 'undefined';
// 使用示例
console.log(isBrowser()); // 在浏览器中为 true,在 Node.js 中为 false
17. 平滑滚动到顶部 (Smooth Scroll to Top)
场景:点击按钮后,页面平滑地滚动回页面顶部。
代码:
function smoothScrollToTop() {
window.scrollTo({
top: 0,
behavior: 'smooth',
});
}
// 使用示例
// 在按钮的点击事件中调用 smoothScrollToTop()
18. 获取数据类型 (Get Type)
场景:比 typeof
更精确地获取一个变量的数据类型。
代码:
function getType(value) {
return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
}
// 使用示例
console.log(getType([])); // "array"
console.log(getType({})); // "object"
console.log(getType(new Date())); // "date"
19. 函数只执行一次 (Once)
场景:创建一个只能被调用一次的函数。
代码:
function once(fn) {
let hasBeenCalled = false;
let result;
return function(...args) {
if (!hasBeenCalled) {
hasBeenCalled = true;
result = fn.apply(this, args);
}
return result;
};
}
// 使用示例
const initApp = once(() => console.log('App Initialized!'));
initApp(); // 输出 "App Initialized!"
initApp(); // 不会再输出
20. 截断字符串 (Truncate String)
场景:如果字符串超过指定长度,则截断并添加省略号。
代码:
function truncateString(str, maxLength) {
if (str.length <= maxLength) return str;
return str.slice(0, maxLength) + '...';
}
// 使用示例
const longText = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
console.log(truncateString(longText, 20)); // 输出 "Lorem ipsum dolor si..."
以上就是我为你精选的20个工具函数。当然,这只是冰山一角,一个强大的工具库是持续迭代和丰富的过程。你可以将它们收藏起来,根据自己的项目需求进行修改和扩展,逐步打造属于你自己的“工具库" 谢谢大家🙂