TS/JS:覆盖函数并在其中调用原始函数 [英] TS / JS: Overwrite a function and call original function within

查看:98
本文介绍了TS/JS:覆盖函数并在其中调用原始函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否有一种方法可以修改TypeScript中的函数并访问其中的原始函数.这是我如何工作的一个示例:

I'd like to know if there's a way to modify a function in TypeScript and access the original function within. This is an example of how I got it to work:

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!"

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

This way I was able to add a warning to my shout function whenever it's called - but I feel like that's an ugly way to do it, so I wonder if there's a better way.

推荐答案

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

The OP's approach is the most intuitive/natural one. With JavaScript applications one sometimes is in need of intercepting and/or modifying the control flow of functionality one does not own or is, for other reasons, not allowed to touch.

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

For exactly this scenario there is no other way than to preserve and alter such logic by wrapping their original implementation. This ability is not unique to JavaScript. There is quite a history of programming languages that enable Metaprogramming via Reflection and Self-Modification.

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

Of cause one could/should provide bulletproof but handy abstractions for all the possibly modifier use cases that one can think of ... starting right away with the OP's use case that is the most obvious and easiest to implement one, which could be handled by e.g a before modifier ...

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中启用 方法修饰符 .

As one can see from the example code, which uses the additionally provided implementation, Function.prototype is quite comfortable for enabling method modifiers in JavaScript.

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

But regardless of how/where one does implement such modifier functionality, following applies to any reliable modifier code (Bergi already did point to it) ...

  1. 修饰符必须支持 target 对象(如果需要,用于委派正确的 this 上下文).
  2. 修饰符必须正确地转发包装方法的参数,或者分别处理其调用失败的异常的返回值.
  1. The modifier has to support a target object (for delegating the correct this context, if needed).
  2. The modifier has to either correctly forward a wrapped method's arguments or handle its return value respectively the exception of its failing invocation.

我不介意有一天JavaScript正式启用... Function.prototype [ afterFinally ] .

I wouldn't mind if, at one day, JavaScript officially features ... Function.prototype[before|after|around|afterThrowing|afterFinally].

这篇关于TS/JS:覆盖函数并在其中调用原始函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆