JavaScript进阶:手写实现10个核心高阶函数
2025.09.19 12:47浏览量:1简介:本文深入解析JavaScript进阶开发中必须掌握的10个核心高阶函数的手写实现,涵盖函数式编程、异步控制、数据结构等关键领域,提供可复用的代码模板和性能优化方案。
一、函数式编程核心:柯里化与反柯里化
1.1 通用柯里化函数
柯里化是将多参数函数转换为连续单参数函数的技术。实现时需处理参数累积和自动执行条件:
function curry(fn) {return function curried(...args) {if (args.length >= fn.length) {return fn.apply(this, args);} else {return function(...args2) {return curried.apply(this, args.concat(args2));}}}}// 使用示例const add = curry((a, b, c) => a + b + c);console.log(add(1)(2)(3)); // 6console.log(add(1, 2)(3)); // 6
关键点:通过fn.length判断参数是否收集完毕,利用闭包保存中间状态。性能优化可添加缓存机制,避免重复创建函数。
1.2 反柯里化实现
反柯里化将方法从特定对象解耦,增强通用性:
function unCurry(fn) {return function(obj, ...args) {return fn.apply(obj, args);}}const push = unCurry(Array.prototype.push);let obj = { length: 0 };push(obj, 1, 2, 3);console.log(obj); // { '0': 1, '1': 2, '2': 3, length: 3 }
应用场景:当需要将对象方法作为通用函数使用时,如实现跨类型操作。
二、异步控制进阶:Promise与Generator
2.1 手写Promise实现
完整实现需包含状态管理、链式调用和异常处理:
class MyPromise {constructor(executor) {this.state = 'pending';this.value = undefined;this.reason = undefined;this.onFulfilledCallbacks = [];this.onRejectedCallbacks = [];const resolve = (value) => {if (this.state === 'pending') {this.state = 'fulfilled';this.value = value;this.onFulfilledCallbacks.forEach(fn => fn());}};const reject = (reason) => {if (this.state === 'pending') {this.state = 'rejected';this.reason = reason;this.onRejectedCallbacks.forEach(fn => fn());}};try {executor(resolve, reject);} catch (err) {reject(err);}}then(onFulfilled, onRejected) {// 实现链式调用...}}
核心机制:状态机管理(pending→fulfilled/rejected)、微任务队列模拟(可用setTimeout替代)、值穿透处理。
2.2 Generator自动执行器
将Generator函数转换为类似async/await的语法:
function co(gen) {return new Promise((resolve, reject) => {const iterator = gen();function step(nextFn) {try {const { value, done } = nextFn();if (done) return resolve(value);Promise.resolve(value).then(v => step(() => iterator.next(v)),e => step(() => iterator.throw(e)));} catch (err) {reject(err);}}step(() => iterator.next());});}// 使用示例co(function* () {const a = yield Promise.resolve(1);const b = yield Promise.resolve(a + 1);return b;}).then(console.log); // 2
实现要点:递归执行Generator、自动处理Promise、错误传播机制。
三、数据结构操作:深度克隆与扁平化
3.1 深度克隆实现
处理循环引用、特殊对象(Date、RegExp等)和Symbol属性:
function deepClone(obj, hash = new WeakMap()) {if (obj === null || typeof obj !== 'object') return obj;if (hash.has(obj)) return hash.get(obj);let clone;if (obj instanceof Date) clone = new Date(obj);else if (obj instanceof RegExp) clone = new RegExp(obj);else {clone = Array.isArray(obj) ? [] : {};hash.set(obj, clone);Reflect.ownKeys(obj).forEach(key => {if (typeof key === 'symbol') {clone[key] = deepClone(obj[key], hash);} else {clone[key] = deepClone(obj[key], hash);}});}return clone;}
关键处理:使用WeakMap解决循环引用,Reflect.ownKeys获取所有属性(包括不可枚举和Symbol)。
3.2 数组扁平化实现
支持指定深度和自动判断深度:
function flatten(arr, depth = Infinity) {let result = [];for (const item of arr) {if (Array.isArray(item) && depth > 0) {result.push(...flatten(item, depth - 1));} else {result.push(item);}}return result;}// 使用示例console.log(flatten([1, [2, [3, [4]]]], 2)); // [1, 2, 3, [4]]
性能优化:使用展开运算符替代concat,减少中间数组创建。
四、高阶工具函数:组合与管道
4.1 函数组合实现
从右到左执行函数:
function compose(...fns) {return function(arg) {return fns.reduceRight((prev, fn) => fn(prev), arg);}}// 使用示例const add5 = x => x + 5;const multiply2 = x => x * 2;const result = compose(multiply2, add5)(10); // 30
4.2 管道函数实现
从左到右执行函数:
function pipe(...fns) {return function(arg) {return fns.reduce((prev, fn) => fn(prev), arg);}}// 使用示例const result = pipe(add5, multiply2)(10); // 30
应用场景:构建数据处理流水线,提升代码可读性。
五、性能优化技巧
- 尾递归优化:对于支持ES6的环境,使用尾调用形式避免栈溢出
- 记忆化缓存:为计算密集型函数添加缓存
function 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;}}
惰性求值:延迟计算直到真正需要
function lazy(fn) {let executed = false;let result;return function() {if (!executed) {result = fn.apply(this, arguments);executed = true;}return result;}}
六、实际应用建议
- 测试驱动开发:为每个手写函数编写单元测试
// 示例测试用例describe('deepClone', () => {it('should clone object with circular reference', () => {const obj = { a: 1 };obj.self = obj;const clone = deepClone(obj);expect(clone).not.toBe(obj);expect(clone.self).toBe(clone);});});
- 性能基准测试:使用
console.time()对比原生方法 - 渐进式重构:先实现基础版本,再逐步优化
七、常见问题解决方案
- this绑定问题:在柯里化时保留原始this
function bindThis(fn, context) {return function(...args) {return fn.apply(context, args);}}
- 参数顺序处理:实现部分应用时保持参数灵活性
function partial(fn, ...presetArgs) {return function(...laterArgs) {const args = [...presetArgs, ...laterArgs];return fn.apply(this, args);}}
- 异步错误处理:完善Promise的catch链
通过系统掌握这些核心函数的手写实现,开发者能够深入理解JavaScript底层机制,提升代码质量和开发效率。建议从简单函数开始实践,逐步构建自己的工具库,最终达到灵活运用函数式编程解决复杂问题的水平。

发表评论
登录后可评论,请前往 登录 或 注册