/**
* js-utils.js
* 实用原生 JS 工具函数合集(支持按需 import)
* 现代浏览器 / Node ESM 通用
*/
/* ------------------ 数组与集合 ------------------ */
/**
* 数组去重(基于 Set)
* @param {Array} arr
* @returns {Array}
*/
export const uniqArray = (arr) => [...new Set(arr)];
/**
* 判断元素是否已存在(Set 快速查找)
* @param {Set} set
* @param {*} value
* @returns {boolean}
*/
export const hasInSet = (set, value) => set.has(value);
/* ------------------ 对象操作 ------------------ */
/**
* 过滤对象中的空值字段(空字符串、null、undefined)
* @param {Object} obj
* @returns {Object}
*/
export const filterEmptyFields = (obj) =>
Object.fromEntries(Object.entries(obj).filter(([_, v]) => v != null && v !== ""));
/**
* 对象数组互转
* @param {Object} obj
* @returns {Array<[string, any]>}
*/
export const toEntries = (obj) => Object.entries(obj);
/**
* 将 entries 数组转为对象
* @param {Array<[string, any]>} entries
* @returns {Object}
*/
export const fromEntries = (entries) => Object.fromEntries(entries);
/* ------------------ 默认值处理 ------------------ */
/**
* 安全获取默认值(只判断 null/undefined)
* @param {*} value
* @param {*} defaultValue
* @returns {*}
*/
export const safeDefault = (value, defaultValue) => value ?? defaultValue;
/**
* 对象属性安全赋默认值(仅在属性为 null/undefined 时生效)
* @param {Object} obj
* @param {string} key
* @param {*} defaultValue
*/
export const ensureDefault = (obj, key, defaultValue) => {
obj[key] ??= defaultValue;
};
/* ------------------ 国际化 ------------------ */
/**
* 本地化货币格式化
* @param {number} value
* @param {string} locale 例如 "zh-CN"、"en-US"
* @param {string} currency 例如 "CNY"、"USD"
* @returns {string}
*/
export const formatCurrency = (value, locale = "zh-CN", currency = "CNY") =>
new Intl.NumberFormat(locale, { style: "currency", currency }).format(value);
/**
* 本地化日期格式化
* @param {Date} date
* @param {string} locale
* @returns {string}
*/
export const formatDateTime = (date = new Date(), locale = "zh-CN") =>
new Intl.DateTimeFormat(locale, {
year: "numeric",
month: "long",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}).format(date);
/* ------------------ DOM 工具 ------------------ */
/**
* 懒加载图片(IntersectionObserver)
* @param {string} selector 图片选择器
*/
export const lazyLoadImages = (selector = ".lazy-img") => {
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
document.querySelectorAll(selector).forEach((img) => observer.observe(img));
};
/**
* 向上查找最近的匹配父元素
* @param {Element} element
* @param {string} selector
* @returns {Element|null}
*/
export const findClosest = (element, selector) => element.closest(selector);
/* ------------------ Promise 工具 ------------------ */
/**
* 批量请求(不因单个失败中断)
* @param {Array<Promise>} promises
* @returns {Promise<{fulfilled: any[], rejected: any[]}>}
*/
export const allSettledSafe = async (promises) => {
const results = await Promise.allSettled(promises);
return {
fulfilled: results
.filter((r) => r.status === "fulfilled")
.map((r) => r.value),
rejected: results
.filter((r) => r.status === "rejected")
.map((r) => r.reason),
};
};
/* ------------------ URL 工具 ------------------ */
/**
* 解析 URL 参数为对象
* @param {string} url
* @returns {Object}
*/
export const parseUrlParams = (url) =>
Object.fromEntries(new URL(url).searchParams.entries());
/**
* 设置 URL 参数(返回新 URL)
* @param {string} baseUrl
* @param {Object} params
* @returns {string}
*/
export const buildUrl = (baseUrl, params = {}) => {
const url = new URL(baseUrl);
Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
return url.href;
};
/* ------------------ 迭代工具 ------------------ */
/**
* 安全遍历(支持 break / continue)
* @param {Iterable} iterable
* @param {Function} callback
*/
export const forOf = (iterable, callback) => {
for (const item of iterable) {
const result = callback(item);
if (result === false) break; // 手动中断
}
};
/* ------------------ 模块异步加载 ------------------ */
/**
* 动态导入模块(Top-level await 替代)
* @param {string} path
* @returns {Promise<*>}
*/
export const importAsync = async (path) => await import(path);
简洁函数库版
最新推荐文章于 2025-12-15 15:15:21 发布
6万+

被折叠的 条评论
为什么被折叠?



