1. 精確獲取小數位數
/*** 獲取數字的小數位數(支持科學計數法)* @param {number|string} num - 要檢查的數字,可以是數字或字符串形式* @returns {number} 返回小數部分的位數* * 實現原理:* 1. 處理科學計數法(如1.23e-5)* 2. 常規數字直接計算小數點后的位數* 3. 自動忽略末尾無意義的0(如12.340返回2位)* * 示例:* getDecimalPlaces(123.456) => 3* getDecimalPlaces(1.23e-5) => 7 (0.0000123)*/
function getDecimalPlaces(num) {// 轉換為字符串并處理科學計數法const numStr = String(num).toLowerCase();// 處理科學計數法(如1.23e-5)if (numStr.includes('e')) {const [base, exponent] = numStr.split('e');const baseDecimal = base.split('.')[1]?.length || 0;// 計算實際小數位數 = 基數小數位數 - 指數絕對值return Math.max(0, baseDecimal - parseInt(exponent));}// 常規數字處理const decimalIndex = numStr.indexOf('.');// 沒有小數點返回0,否則計算小數點后的字符數return decimalIndex === -1 ? 0 : numStr.length - decimalIndex - 1;
}
2. 深度對象比較(遞歸實現)
/*** 深度比較兩個對象或值是否完全相等(遞歸實現)* @param {*} obj1 - 第一個比較對象* @param {*} obj2 - 第二個比較對象* @returns {boolean} 如果相等返回true,否則false* * 功能特點:* 1. 支持基本類型比較(number, string, boolean等)* 2. 支持數組比較(包括嵌套數組)* 3. 支持對象比較(包括嵌套對象)* 4. 處理了循環引用的情況* * 示例:* deepEqual({a:1,b:{c:2}}, {a:1,b:{c:2}}) => true*/
function deepEqual(obj1, obj2) {// 快速路徑:如果是同一個對象或值相同if (obj1 === obj2) return true;// 處理null/undefined和基本類型if (obj1 == null || obj2 == null || typeof obj1 !== 'object' || typeof obj2 !== 'object') {return obj1 === obj2;}// 處理數組比較if (Array.isArray(obj1) && Array.isArray(obj2)) {// 數組長度不同直接返回falseif (obj1.length !== obj2.length) return false;// 遞歸比較每個元素for (let i = 0; i < obj1.length; i++) {if (!deepEqual(obj1[i], obj2[i])) return false;}return true;}// 獲取兩個對象的鍵const keys1 = Object.keys(obj1);const keys2 = Object.keys(obj2);// 鍵數量不同直接返回falseif (keys1.length !== keys2.length) return false;// 檢查所有鍵值是否相等for (const key of keys1) {// 檢查key是否存在和對應的值是否相等if (!keys2.includes(key) || !deepEqual(obj1[key], obj2[key])) {return false;}}return true;
}
3. 安全的深拷貝實現
/*** 深拷貝對象或數組(解決JSON.parse(JSON.stringify())的局限)* @param {*} obj - 要拷貝的對象* @returns {*} 返回深拷貝后的新對象* * 與JSON方法的區別:* 1. 保留Date對象(而不是變成字符串)* 2. 保留RegExp對象(而不是變成空對象)* 3. 處理循環引用(本示例未實現,實際項目需要額外處理)* * 示例:* const obj = {a:1, b: {c:2}};* const copy = deepClone(obj);*/
function deepClone(obj) {// 處理基本類型和null/undefinedif (obj === null || typeof obj !== 'object') {return obj;}// 處理Date對象if (obj instanceof Date) {return new Date(obj.getTime()); // 復制時間戳}// 處理數組if (Array.isArray(obj)) {return obj.map(item => deepClone(item)); // 遞歸拷貝每個元素}// 處理普通對象const cloned = {};for (const key in obj) {// 只拷貝對象自身的屬性(不拷貝原型鏈上的)if (obj.hasOwnProperty(key)) {cloned[key] = deepClone(obj[key]); // 遞歸拷貝每個屬性}}return cloned;
}
4. 防抖與節流函數對比
/*** 防抖函數(延遲執行)* @param {Function} fn - 要執行的函數* @param {number} delay - 延遲時間(毫秒)* @returns {Function} 返回包裝后的函數* * 應用場景:* 1. 搜索框輸入(停止輸入300ms后再搜索)* 2. 窗口resize事件(停止調整300ms后再計算布局)* * 原理:* 每次調用都清除之前的定時器,重新計時*/
function debounce(fn, delay = 300) {let timer = null;return function(...args) {clearTimeout(timer); // 清除之前的定時器timer = setTimeout(() => {fn.apply(this, args); // 延遲執行}, delay);};
}/*** 節流函數(固定間隔執行)* @param {Function} fn - 要執行的函數* @param {number} interval - 執行間隔(毫秒)* @returns {Function} 返回包裝后的函數* * 應用場景:* 1. 滾動事件(每100ms檢查一次位置)* 2. 鼠標移動事件(避免過于頻繁的觸發)* * 原理:* 記錄上次執行時間,只有超過間隔才執行*/
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. 增強版類型檢測
/*** 精確判斷JavaScript數據類型* @param {*} value - 要檢測的值* @returns {string} 返回類型字符串* * 支持的類型:* 'null', 'undefined', 'boolean', 'number', 'string', * 'symbol', 'function', 'array', 'date', 'regexp', * 'error', 'map', 'set', 'weakmap', 'weakset', 'promise', 'object'*/
function getType(value) {// 優先處理null和undefinedif (value === null) return 'null';if (value === undefined) return 'undefined';// 處理基本類型const type = typeof value;if (type !== 'object') return type;// 使用Object.prototype.toString獲取精確類型const toString = Object.prototype.toString.call(value);// 類型映射表const typeMap = {'[object Array]': 'array','[object Date]': 'date','[object RegExp]': 'regexp','[object Error]': 'error','[object Map]': 'map','[object Set]': 'set','[object WeakMap]': 'weakmap','[object WeakSet]': 'weakset','[object Promise]': 'promise'};// 返回映射表中的類型或默認objectreturn typeMap[toString] || 'object';
}
6. 對象數組按屬性去重
/*** 對象數組根據指定屬性去重* @param {Array} arr - 對象數組* @param {string} key - 用作比較的屬性名* @returns {Array} 返回去重后的新數組* * 實現原理:* 使用Set記錄已經出現過的屬性值* 只保留每個屬性值第一次出現的對象* * 示例:* uniqueByKey([{id:1},{id:2},{id:1}], 'id') => [{id:1},{id:2}]*/
function uniqueByKey(arr, key) {const seen = new Set(); // 存儲已出現的key值return arr.filter(item => {const val = item[key]; // 獲取當前對象的key屬性值if (seen.has(val)) {return false; // 如果已經存在則過濾掉}seen.add(val); // 記錄新的key值return true; // 保留當前對象});
}
7. 高級數字格式化
/*** 數字格式化(千分位和小數位控制)* @param {number} num - 要格式化的數字* @param {number} decimals - 保留小數位數(默認2)* @returns {string} 格式化后的字符串* * 功能特點:* 1. 自動添加千分位逗號* 2. 精確控制小數位數* 3. 處理四舍五入* * 示例:* formatNumber(1234567.89123, 2) => "1,234,567.89"*/
function formatNumber(num, decimals = 2) {// 先轉換為指定位數的小數字符串const numStr = num.toFixed(decimals);// 拆分整數和小數部分const [integer, decimal] = numStr.split('.');// 添加千分位逗號const formattedInteger = integer.replace(/\B(?=(\d{3})+(?!\d))/g, ',');// 如果有小數部分則拼接,否則只返回整數return decimal ? `${formattedInteger}.${decimal}` : formattedInteger;
}
8. 安全的JSON解析
/*** 安全的JSON解析(帶錯誤處理)* @param {string} jsonStr - JSON字符串* @param {*} defaultValue - 解析失敗時返回的默認值* @returns {*} 解析后的對象或默認值* * 為什么要用:* 1. JSON.parse在解析錯誤字符串時會拋出異常* 2. 這個封裝確保始終返回有效結果* * 示例:* safeParse('{"a":1}') => {a:1}* safeParse('invalid', {}) => {}*/
function safeParse(jsonStr, defaultValue = null) {try {return JSON.parse(jsonStr);} catch (e) {console.error('JSON解析失敗:', e);return defaultValue;}
}