如何拦截JavaScript中的函数调用来抓取函数调用名

How to intercept a function call in JavaScript to grab the function call name

我不确定如何用标题来表达,所以我会更详细地介绍。

我想做的是有一些 object 叫做 car

object car 包含两个 object 称为 tireengine.

我想发生的事情是可以说,

car.start();

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

综上所述

我希望能够调用 object 并让调用的 object 将其传递给实现该函数调用的任何人。

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

如有任何想法,我们将不胜感激。谢谢!

示例代码

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。 ** 我知道我可以对函数调用进行硬编码并让它通过,但我正在尝试动态执行此操作,因此我不必声明可以调用的每个函数。所以我想动态地做这个。

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

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();

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

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

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

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

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();