Javascript TS/JS:覆盖一个函数并在其中调用原始函数

Javascript TS/JS:覆盖一个函数并在其中调用原始函数,javascript,typescript,methods,metaprogramming,modifier,Javascript,Typescript,Methods,Metaprogramming,Modifier,我想知道是否有办法修改TypeScript中的函数并访问其中的原始函数。这是我如何让它工作的一个例子: let obj = { shout: () => { console.log("AHHHHH!"); }, }; let s = obj.shout; obj.shout = () => { console.log("I'm going to shout."); s(); }; obj.shout(); //-&

我想知道是否有办法修改TypeScript中的函数并访问其中的原始函数。这是我如何让它工作的一个例子:

let obj = {
  shout: () => {
    console.log("AHHHHH!");
  },
};

let s = obj.shout;

obj.shout = () => {
  console.log("I'm going to shout.");
  s();
};

obj.shout(); //-> "I'm going to shout", "AHHHHH!"

通过这种方式,我可以在每次调用shout函数时向其添加警告,但我觉得这是一种丑陋的方式,因此我想知道是否有更好的方法。

当您将新函数分配给现有对象时,就像您丢失了对旧值的引用一样

但是如果您使用类,您确实可以通过
super
访问重载方法

class ObjA {
    shout() {
        console.log('AHHHHH!')
    }
}

class ObjB extends ObjA {
    shout() {
        super.shout()
        console.log("I'm going to shout.")
    }
}

const obj = new ObjB()
obj.shout() //-> "I'm going to shout", "AHHHHH!"

将新函数指定给现有对象时,会丢失对旧值的引用

但是如果您使用类,您确实可以通过
super
访问重载方法

class ObjA {
    shout() {
        console.log('AHHHHH!')
    }
}

class ObjB extends ObjA {
    shout() {
        super.shout()
        console.log("I'm going to shout.")
    }
}

const obj = new ObjB()
obj.shout() //-> "I'm going to shout", "AHHHHH!"

OP的方法是最直观/自然的方法。对于JavaScript应用程序,有时需要拦截和/或修改功能的控制流,因为其他原因,不允许触摸

对于这个场景,除了通过包装它们的原始实现来保存和修改这样的逻辑之外,没有其他方法。这种能力不是JavaScript独有的。通过反射自我修改来启用元编程的编程语言已有相当长的历史

当然,我们可以/应该为我们能想到的所有可能的修改器用例提供防弹但方便的抽象。。。从OP的用例开始,它是最明显和最容易实现的用例,可以通过例如之前的修改器来处理

const obj={
shout:function(…args){
console.log('ahhhh!');
log('args:',args);
log('this is me:',this);
}
};
obj.shout();
obj.shout=obj.shout.before(函数(){
log(“我要喊了。”);
},obj);
obj.shout(‘修饰语’之前的‘测试’);
常数另一个={
名字:“另一个”
};
obj.shout.call(另一个“授权和自我反思”);
/*
console.log(
'Object.getOwnPropertyDescriptors(Function.prototype):',
Object.getOwnPropertyDescriptors(Function.prototype)
);
*/
.as控制台包装{最小高度:100%!重要;顶部:0;}

(功能(功能){
const fctPrototype=Function.prototype;
常量函数类型=(函数类型);
函数isFunction(类型){
返回(
(typeof type==函数类型)
&&(typeof type.call==函数类型)
&&(typeof type.apply==函数类型)
);
}
函数getSanitizedTarget(目标){
返回((target!=null)&&target)| null;
}
/*修饰符之前的函数*/(处理程序,目标){
目标=getSanitizedTarget(目标);
const procedure=this;
返回(
isFunction(处理程序)&&
isFunction(继续)&&
函数(){
const context=target | | getSanitizedTarget(this);
常量args=参数;
//应用(上下文,参数);
调用(上下文,参数);
返回procedure.apply(上下文,参数);
}
)| |继续;
}
//before.toString=()=>'before(){[native code]}';
Object.defineProperty(fctPrototype,'before'{
对,,
可写:对,
值:在/*修饰符*之前
});
}(功能);

OP的方法是最直观/自然的方法。对于JavaScript应用程序,有时需要拦截和/或修改功能的控制流,因为其他原因,不允许触摸

对于这个场景,除了通过包装它们的原始实现来保存和修改这样的逻辑之外,没有其他方法。这种能力不是JavaScript独有的。通过反射自我修改来启用元编程的编程语言已有相当长的历史

当然,我们可以/应该为我们能想到的所有可能的修改器用例提供防弹但方便的抽象。。。从OP的用例开始,它是最明显和最容易实现的用例,可以通过例如之前的修改器来处理

const obj={
shout:function(…args){
console.log('ahhhh!');
log('args:',args);
log('this is me:',this);
}
};
obj.shout();
obj.shout=obj.shout.before(函数(){
log(“我要喊了。”);
},obj);
obj.shout(‘修饰语’之前的‘测试’);
常数另一个={
名字:“另一个”
};
obj.shout.call(另一个“授权和自我反思”);
/*
console.log(
'Object.getOwnPropertyDescriptors(Function.prototype):',
Object.getOwnPropertyDescriptors(Function.prototype)
);
*/
.as控制台包装{最小高度:100%!重要;顶部:0;}

(功能(功能){
const fctPrototype=Function.prototype;
常量函数类型=(函数类型);
函数isFunction(类型){
返回(
(typeof type==函数类型)
&&(typeof type.call==函数类型)
&&(typeof type.apply==函数类型)
);
}
函数getSanitizedTarget(目标){
返回((target!=null)&&target)| null;
}
/*修饰符之前的函数*/(处理程序,目标){
目标=getSanitizedTarget(目标);
const procedure=this;
返回(
isFunction(处理程序)&&
isFunction(继续)&&
函数(){
const context=target | | getSanitizedTarget(this);
常量args=参数;
//应用(上下文,参数);
调用(上下文,参数);
返回procedure.apply(上下文,参数);
}
)| |继续;