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

问题描述

我想知道是否有一种方法可以修改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!"

通过这种方式,无论何时调用它,我都可以向我的喊叫功能添加警告-但我觉得这样做很丑陋,所以我想知道是否有更好的方法。

解决方法

OP的方法是最直观/自然的方法。对于JavaScript应用程序,有时需要 拦截 和/或 修改 控件功能 ,一个人不拥有或由于其他原因而被禁止触摸。

对于这种情况,除了包装原始实现来保留和更改这种逻辑外,别无其他方法。此功能并非JavaScript独有。已有很长的编程语言可以通过 Reflection Self->实现 元编程 修改

当然,人们可以/应该为所有可能想到的修饰符用例提供防弹但方便的抽象……从最明显,最容易实现的OP用例开始,这可以由例如 before 修饰符...

处理

const obj = {
  shout: function (...args) {

    console.log('AHHHHH!');

    console.log('args : ',args);
    console.log('this is me : ',this);
  }
};
obj.shout();


obj.shout = obj.shout.before(function () {

  console.log("I'm going to shout.");

},obj);

obj.shout('test of "before" modifier');


const anotherOne = {
  name: 'anotherOne'
};
obj.shout.call(anotherOne,'delegation and self reflection');


/*
console.log(
  'Object.getOwnPropertyDescriptors(Function.prototype) :',Object.getOwnPropertyDescriptors(Function.prototype)
);
*/
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
  (function (Function) {

    const fctPrototype = Function.prototype;
    const FUNCTION_TYPE = (typeof Function);

    function isFunction(type) {
      return (
           (typeof type == FUNCTION_TYPE)
        && (typeof type.call == FUNCTION_TYPE)
        && (typeof type.apply == FUNCTION_TYPE)
      );
    }
    function getSanitizedTarget(target) {
      return ((target != null) && target) || null;
    }

    function before/*Modifier*/(handler,target) {
      target = getSanitizedTarget(target);

      const proceed = this;
      return (

        isFunction(handler) &&
        isFunction(proceed) &&

        function () {
          const context = target || getSanitizedTarget(this);
          const args = arguments;

        //handler.apply(context,args);
          handler.call(context,args);

          return proceed.apply(context,args);
        }

      ) || proceed;
    }
    // before.toString = () => 'before() { [native code] }';

    Object.defineProperty(fctPrototype,'before',{
      configurable: true,writable: true,value: before/*Modifier*/ 
    });

  }(Function));
</script>

从使用附加提供的实现的示例代码中可以看出,Function.prototype非常适合在JavaScript中启用 方法修饰符

>

但是,无论如何/在何处实现此类修改器功能,以下内容都适用于任何可靠的修改器代码( Bergi 已经指出了)...

  1. 修饰符必须支持target对象(用于根据需要委派正确的this上下文)。
  2. 修饰符必须正确地转发包装方法的参数,或者分别处理其调用失败的异常的返回值。

我不介意有一天JavaScript正式启用... Function.prototype[ before | after | around | afterThrowing | afterFinally ]

,

当您为现有对象分配新功能时,就像丢失了对旧值的引用一样。

但是,如果您使用类,则可以通过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!"

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...