高级用法 #
深拷贝 #
什么是深拷贝? #
深拷贝是指创建一个对象的完整副本,包括所有嵌套的属性,修改副本不会影响原对象。
text
┌─────────────────────────────────────────────────────────────┐
│ 浅拷贝 vs 深拷贝 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 原对象 │
│ ┌─────────────────────────────────────────┐ │
│ │ { a: 1, b: { c: 2 } } │ │
│ └─────────────────────────────────────────┘ │
│ │ │
│ ┌──────────┴──────────┐ │
│ ▼ ▼ │
│ 浅拷贝 深拷贝 │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ a: 1 (独立) │ │ a: 1 (独立) │ │
│ │ b: ──────────────────►│ b: { c: 2 } │ │
│ │ (引用原对象) │ │ (独立副本) │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
deepCopy 实现 #
javascript
export const deepCopy = (obj, map) => {
map = map || new WeakMap();
if (typeof obj !== 'object' || obj === null) {
return obj;
}
if (map.has(obj)) {
return map.get(obj);
}
let clone;
if (Array.isArray(obj)) {
clone = [];
} else {
clone = {};
}
map.set(obj, clone);
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
clone[key] = deepCopy(obj[key], map);
}
}
return clone;
};
使用示例 #
javascript
import { deepCopy } from './utils';
const original = {
name: 'John',
age: 25,
address: {
city: 'Beijing',
country: 'China'
},
hobbies: ['reading', 'coding']
};
const copy = deepCopy(original);
copy.name = 'Jane';
copy.address.city = 'Shanghai';
copy.hobbies.push('gaming');
console.log(original.name);
console.log(original.address.city);
console.log(original.hobbies);
处理特殊类型 #
javascript
const deepCopyAdvanced = (obj, map = new WeakMap()) => {
if (obj === null || typeof obj !== 'object') {
return obj;
}
if (map.has(obj)) {
return map.get(obj);
}
if (obj instanceof Date) {
return new Date(obj);
}
if (obj instanceof RegExp) {
return new RegExp(obj.source, obj.flags);
}
if (obj instanceof Map) {
const clone = new Map();
map.set(obj, clone);
obj.forEach((value, key) => {
clone.set(deepCopyAdvanced(key, map), deepCopyAdvanced(value, map));
});
return clone;
}
if (obj instanceof Set) {
const clone = new Set();
map.set(obj, clone);
obj.forEach(value => {
clone.add(deepCopyAdvanced(value, map));
});
return clone;
}
if (Array.isArray(obj)) {
const clone = [];
map.set(obj, clone);
obj.forEach((item, index) => {
clone[index] = deepCopyAdvanced(item, map);
});
return clone;
}
const clone = {};
map.set(obj, clone);
Object.keys(obj).forEach(key => {
clone[key] = deepCopyAdvanced(obj[key], map);
});
Object.getOwnPropertySymbols(obj).forEach(sym => {
clone[sym] = deepCopyAdvanced(obj[sym], map);
});
return clone;
};
深合并 #
什么是深合并? #
深合并是指递归地合并两个或多个对象,嵌套对象也会被合并而不是覆盖。
deepMerge 实现 #
javascript
const isObject = (obj) => {
return obj !== null && typeof obj === 'object' && !Array.isArray(obj);
};
export const deepMerge = (a, b) => {
const merged = { ...a };
for (const key in b) {
if (b.hasOwnProperty(key)) {
const aVal = a[key];
const bVal = b[key];
if (isObject(aVal) && isObject(bVal)) {
merged[key] = deepMerge(aVal, bVal);
} else {
merged[key] = bVal;
}
}
}
return merged;
};
使用示例 #
javascript
import { deepMerge } from './utils';
const defaults = {
theme: 'light',
language: 'zh-CN',
notifications: {
email: true,
push: true,
sound: false
},
privacy: {
profile: 'public',
activity: 'private'
}
};
const userSettings = {
theme: 'dark',
notifications: {
email: false
}
};
const merged = deepMerge(defaults, userSettings);
console.log(merged);
多对象合并 #
javascript
const deepMergeMultiple = (...objects) => {
return objects.reduce((result, obj) => deepMerge(result, obj), {});
};
const config = deepMergeMultiple(
{ a: 1, b: { x: 1 } },
{ b: { y: 2 }, c: 3 },
{ d: 4, b: { z: 3 } }
);
console.log(config);
其他实用函数 #
extendArray #
扩展数组,将数组重复多次。
javascript
export const extendArray = (arr, multiple) => {
let result = [];
for (let i = 0; i < multiple; i++) {
result = result.concat(arr);
}
return result;
};
console.log(extendArray([1, 2, 3], 3));
getCharLength #
计算字符串长度,中文字符算 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;
};
console.log(getCharLength('Hello世界'));
console.log(getCharLength('JavaScript'));
filterEmptyRowsAndColumns #
过滤二维数组中的空行和空列。
javascript
export const filterEmptyRowsAndColumns = (data) => {
const filteredRows = data.filter(row => {
return row.some(cell => cell !== null && cell !== undefined && cell.toString().trim() !== '');
});
const transposed = filteredRows[0].map((_, colIndex) =>
filteredRows.map(row => row[colIndex])
);
const filteredTransposed = transposed.filter(row => {
return row.some(cell => cell !== null && cell !== undefined && cell.toString().trim() !== '');
});
return filteredTransposed[0].map((_, colIndex) =>
filteredTransposed.map(row => row[colIndex])
);
};
const data = [
['', '', ''],
['A', 'B', 'C'],
['D', 'E', 'F'],
['', '', '']
];
console.log(filterEmptyRowsAndColumns(data));
性能优化 #
1. 防抖 #
javascript
const debounce = (fn, delay) => {
let timer = null;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
};
const handleSearch = debounce((query) => {
console.log('搜索:', query);
}, 300);
handleSearch('h');
handleSearch('he');
handleSearch('hello');
2. 节流 #
javascript
const throttle = (fn, delay) => {
let lastTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastTime >= delay) {
fn.apply(this, args);
lastTime = now;
}
};
};
const handleScroll = throttle(() => {
console.log('滚动位置:', window.scrollY);
}, 100);
window.addEventListener('scroll', handleScroll);
3. 惰性函数 #
javascript
const getXHR = () => {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
return new ActiveXObject('Microsoft.XMLHTTP');
}
return null;
};
const getXHRLazy = (() => {
let xhr = null;
return () => {
if (xhr) return xhr;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
return xhr;
};
})();
4. 记忆化 #
javascript
const memoize = (fn) => {
const cache = new Map();
return function(...args) {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
}
const result = fn.apply(this, args);
cache.set(key, result);
return result;
};
};
const fibonacci = memoize((n) => {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
});
console.log(fibonacci(40));
最佳实践 #
1. 错误处理 #
javascript
const safeExecute = (fn, fallback = null) => {
try {
return fn();
} catch (e) {
console.error('执行错误:', e);
return fallback;
}
};
const result = safeExecute(() => JSON.parse('invalid json'), {});
2. 参数验证 #
javascript
const validate = (value, rules) => {
for (const rule of rules) {
if (!rule.test(value)) {
return { valid: false, message: rule.message };
}
}
return { valid: true };
};
const rules = [
{ test: v => v !== undefined, message: '值不能为空' },
{ test: v => typeof v === 'string', message: '值必须是字符串' },
{ test: v => v.length >= 3, message: '长度至少为3' }
];
console.log(validate('hi', rules));
console.log(validate('hello', rules));
3. 类型检查 #
javascript
const TypeCheck = {
isString: v => typeof v === 'string',
isNumber: v => typeof v === 'number' && !isNaN(v),
isBoolean: v => typeof v === 'boolean',
isFunction: v => typeof v === 'function',
isObject: v => v !== null && typeof v === 'object' && !Array.isArray(v),
isArray: v => Array.isArray(v),
isDate: v => v instanceof Date,
isRegExp: v => v instanceof RegExp,
isPromise: v => v instanceof Promise,
isEmpty: v => {
if (v === null || v === undefined) return true;
if (TypeCheck.isArray(v) || TypeCheck.isString(v)) return v.length === 0;
if (TypeCheck.isObject(v)) return Object.keys(v).length === 0;
return false;
}
};
console.log(TypeCheck.isArray([1, 2, 3]));
console.log(TypeCheck.isEmpty({}));
4. 链式调用 #
javascript
class Chain {
constructor(value) {
this.value = value;
}
map(fn) {
this.value = fn(this.value);
return this;
}
filter(fn) {
if (Array.isArray(this.value)) {
this.value = this.value.filter(fn);
}
return this;
}
reduce(fn, initial) {
if (Array.isArray(this.value)) {
this.value = this.value.reduce(fn, initial);
}
return this;
}
value() {
return this.value;
}
}
const result = new Chain([1, 2, 3, 4, 5])
.filter(x => x > 2)
.map(x => x * 2)
.reduce((sum, x) => sum + x, 0)
.value();
console.log(result);
总结 #
本指南涵盖了 JavaScript 工具函数的各个方面:
- 入门基础:了解工具函数的概念和基本使用
- 核心功能:URL 处理、Cookie 操作、日期时间、本地存储
- 进阶功能:文件处理、颜色转换、主题管理
- 高级扩展:加密哈希、深拷贝、深合并、性能优化
通过学习这些内容,你可以:
- 编写更简洁、高效的代码
- 提高开发效率和代码质量
- 构建自己的工具函数库
- 解决常见的开发问题
继续实践和探索,将这些知识应用到实际项目中!
最后更新:2026-04-04