function.prototype 是所有函数对象的原型,可为其添加方法供普通函数调用(箭头函数除外);需避免命名冲突、使用 object.defineproperty 做防御性挂载,并优先选用模块化高阶函数替代。

Function.prototype 是所有函数对象的原型,往它上面添加方法,能让所有函数(包括普通函数、箭头函数除外)直接调用这些方法。但要注意:箭头函数没有自己的 this 和 prototype,所以无法通过这种方式扩展;同时,挂载通用工具函数需避免命名冲突、保持语义清晰、不破坏原有行为。
挂载方式:直接赋值到 Function.prototype
这是最直接的方式,例如添加一个 before 方法,用于在原函数执行前运行前置逻辑:
Function.prototype.before = function (fn) {
const self = this;
return function (...args) {
fn.apply(this, args);
return self.apply(this, args);
};
};
使用示例:
function greet(name) {
console.log(`Hello, ${name}`);
}
const enhanced = greet.before(() => console.log('Preparing...'));
enhanced('Alice');
// 输出:
// Preparing...
// Hello, Alice
常用且安全的工具函数建议
以下几类方法适合挂载,兼顾实用性与低风险:
-
装饰器类:如
before、after、once、throttle、debounce—— 它们返回新函数,不修改原函数 -
元信息类:如
isAsync(判断是否 async 函数)、getParams(提取形参名,需正则或 AST,谨慎使用) -
调试辅助类:如
debug(自动打印入参/返回值)、profile(简单性能统计)
⚠️ 避免挂载可能覆盖原生方法的名字(如 call、bind、toString),也别用太泛的名称如 run、exec。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
兼容性与防御性写法
为防止重复定义或被冻结的对象报错,推荐加一层保护:
if (!Function.prototype.memoize) {
Object.defineProperty(Function.prototype, 'memoize', {
value: function () {
// 实现记忆化逻辑
const cache = new Map();
return function (...args) {
const key = JSON.stringify(args);
if (cache.has(key)) return cache.get(key);
const result = this.apply(this, args);
cache.set(key, result);
return result;
};
},
writable: true,
configurable: true,
enumerable: false // 不出现在 for...in 中
});
}
用 Object.defineProperty 可精确控制属性特性,enumerable: false 是关键,避免污染遍历结果。
为什么不推荐在生产环境广泛使用?
虽然技术上可行,但实际项目中需权衡:
- 全局污染:影响所有函数,第三方库或未来 JS 新增同名方法时可能冲突
- 可维护性差:团队成员未必熟悉自定义原型方法,调试和阅读成本上升
- Tree-shaking 失效:挂载在原型上的方法无法被打包工具静态分析移除
- 更现代的替代方案:用 ES 模块导出高阶函数(如
import { before } from './utils';),更显式、可控、易测试
仅建议在小型脚本、内部工具库或学习场景中尝试,大型项目优先采用组合式工具函数。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










