js 实现before
在JavaScript中,可以通过修改原型链或使用高阶函数来实现类似before的功能,即在目标函数执行前插入自定义逻辑。以下是几种实现方法:
通过原型链扩展Function
为Function原型添加before方法,允许在调用原函数前执行前置函数:
Function.prototype.before = function(beforeFn) {
const originalFn = this;
return function(...args) {
beforeFn.apply(this, args);
return originalFn.apply(this, args);
};
};
// 示例用法
const sayHello = () => console.log("Hello");
const logBefore = () => console.log("About to say hello");
const wrappedFn = sayHello.before(logBefore);
wrappedFn(); // 输出: About to say hello \n Hello
使用高阶函数包装
直接通过函数组合实现前置逻辑,不修改原型:
const before = (beforeFn, originalFn) => (...args) => {
beforeFn.apply(this, args);
return originalFn.apply(this, args);
};
// 示例用法
const sayHi = () => console.log("Hi");
const logTime = () => console.log(`Time: ${new Date().toISOString()}`);
const enhancedHi = before(logTime, sayHi);
enhancedHi(); // 输出时间戳后输出 Hi
保留原函数上下文
确保前置函数和原函数共享相同的this上下文:
Function.prototype.before = function(beforeFn) {
const originalFn = this;
return function() {
beforeFn.call(this);
return originalFn.call(this);
};
};
// 示例:对象方法调用
const obj = {
name: "Alice",
greet: function() { console.log(`My name is ${this.name}`) }
};
obj.logBefore = () => console.log("Starting greeting...");
obj.greet = obj.greet.before(obj.logBefore);
obj.greet(); // 输出前置日志并正确显示name
参数传递处理
显式处理参数传递的场景:
const beforeWithArgs = (beforeFn, mainFn) => (...args) => {
beforeFn(args);
return mainFn(args);
};
// 示例
const add = (a, b) => a + b;
const validate = (args) => {
if (args.some(isNaN)) throw new Error("Invalid numbers");
};
const safeAdd = beforeWithArgs(validate, add);
console.log(safeAdd(2, 3)); // 5
异步场景支持
处理异步前置操作:
Function.prototype.beforeAsync = async function(beforeFn) {
const originalFn = this;
return async function(...args) {
await beforeFn.apply(this, args);
return originalFn.apply(this, args);
};
};
// 示例
const fetchData = async () => "Data";
const checkAuth = async () => {
await new Promise(resolve => setTimeout(resolve, 500));
console.log("Auth checked");
};
const secureFetch = fetchData.beforeAsync(checkAuth);
secureFetch().then(console.log); // 先检查认证后获取数据
以上方法可根据具体需求选择:

- 原型链扩展适合需要全局使用的场景
- 高阶函数适合局部逻辑组合
- 异步版本适用于Promise链式调用
- 注意
this绑定和参数传递的细节差异






