【问题标题】:How to intercept a function call in JavaScript to grab the function call name如何在 JavaScript 中拦截函数调用以获取函数调用名称
【发布时间】:2021-03-11 07:24:03
【问题描述】:

我不知道如何写标题,所以我会更详细地介绍。

我想做的是有一个名为car的对象。

car 对象包含两个名为 tireengine 的对象。

我想要发生的事情是能够说,

car.start();

然后我希望汽车对象能够同时检查 tireengine 以查看它是否包含具有该名称的函数然后调用它。

总结一下

我希望能够调用一个对象并将该对象传递给实现该函数调用的任何人。

我查看了代理模式,但不知道如何动态地将函数调用从对象传递到嵌套对象。

任何想法将不胜感激。谢谢!

示例代码

function engine() {
    return {
        start: () => console.log('start')
    }
}

function tire() {
    return {
        getWidth: () => console.log('get width')
    }
}

function car() {
    this.tire = new tire();
    this.engine = new engine();

    // Pass on function calls made to car over to tire or engine depending on who implemented that function call.
}

// This should print start.
car.start();

**PS。 ** 我知道我可以对函数调用进行硬编码并让它通过,但我正在尝试动态地执行此操作,因此我不必声明每个可以调用的函数。所以我想动态地做到这一点。

【问题讨论】:

  • 也许stackoverflow.com/questions/9779624/… 就是您要找的。​​span>
  • 您的原始问题标题中包含 Design Patterns - 从这个角度来看,您正试图在不支持它的语言中创建多重继承。我不明白为什么代理不起作用。
  • 查看另一个网站的代理设计模式示例,这些功能只是硬编码的。这并没有告诉我如何动态地传递函数。 @fblundun 链接的堆栈溢出问题是我想到的。我不知道代理对象存在。

标签: javascript design-patterns software-design


【解决方案1】:

将它们转换为实际的类,然后从它们的原型中复制属性:

class Engine {
    start() {
        console.log("start");
    }
}

class Tire {
    getWidth() {
        console.log("get width");
    }
}

class Car {
    constructor() {
        this.tire = new Tire();
        this.engine = new Engine();
    }
}

for (const key of Object.getOwnPropertyNames(Engine.prototype)) {
    if (key !== "constructor") {
        Car.prototype[key] = function(...args) { return this.engine[key](...args); };
    }
}

for (const key of Object.getOwnPropertyNames(Tire.prototype)) {
    if (key !== "constructor") {
        Car.prototype[key] = function(...args) { return this.tire[key](...args); };
    }
}

const car = new Car();
car.start();
car.getWidth();

【讨论】:

  • 好主意!我没想到。
【解决方案2】:

解决这个问题:“我查看了代理模式,但不知道如何动态地将函数调用从对象传递到嵌套对象。

您可能错过了检查代理类的“未定义”方法。在下面的代码中注意target[prop] === undefined - 此检查确定目标上是否存在 dynamic 方法。如果没有,则查看 prop 并从嵌入对象调用方法。

如果您不想从嵌入对象中枚举方法,您可以自省它们以找到包含该方法的对象(此处未显示)。

这应该证明代理对象确实可以用来实现您的目标。

function Engine() {
  this.start = () => {
    console.log('started');
  }
}

function Tire() {
  this.getWidth = () => {
    console.log('got width');
  }
}

function Car() {
  this.tire = new Tire();
  this.engine = new Engine();
}

const carProxy = {
  get: function(target, prop, receiver) {
    if (target[prop] === undefined) {
      if (prop === "getWidth") {
        console.log('getting tire width');
        return target.tire.getWidth;
      } else if (prop === "start") {
        console.log('starting');
        return target.engine.start;
      } else {
        return () => {
          console.log('Undefined function');
        }
      }
    }
  }
};
const target = new Car()
const car = new Proxy(target, carProxy);
car.start();
car.getWidth();

【讨论】:

  • 感谢您的回复,但我希望动态执行此操作,而不是对函数调用进行硬编码。
  • 对,这就是我对内省目标对象的评论。您可以在其中一个封装对象中找到缺少的方法并以这种方式调用它。为了简单起见,我没有包含该代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-25
  • 2011-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-28
相关资源
最近更新 更多