我需要以某种方式更新所有函数,以便我可以获得在程序生命周期中调用每个函数的次数

somehow I need to update all the functions so that I can get how many times each function is called during the program lifecycle

我的系统中有一个平方函数,例如

function square(a) {
  console.log(a);
  return a * a;
}

这个square函数在程序的生命周期中被调用了很多次

square(5);
square(1);
square(2);
square(3);

现在的问题是我想获得在任何给定时间调用时代平方函数的计数,例如 square.count 应该 return 4

该解决方案不仅应适用于平方函数,而且还应具有可扩展性并适用于系统中可用的其他函数。例如,如果我也有一个 power(a,n) 函数,那么我应该能够通过 power.count

之类的东西获得幂函数的计数

您可以创建一个包装目标函数并记录该信息的函数,如下所示:

function addCounter(fn) {
    // Create a wrapper function
    const newfn = function(...args) {
        // In the wrapper, increment the count
        ++newfn.count;
        // Call original and return its return value
        return fn.apply(this, args);
    };
    // Set up the count
    newfn.count = 0;
    // Ensure the new function's `length` matches the original
    // (in case you have anything relying on it)
    Object.defineProperty(newfn, "length", {
        value: fn.length,
        configurable: true,
    });
    // Return the new function
    return newfn;
}

然后你像这样替换函数:

square = addCounter(square);

现在无论何时调用它,计数器都会递增。

实例:

function addCounter(fn) {
    // Create a wrapper function
    const newfn = function(...args) {
        // In the wrapper, increment the count
        ++newfn.count;
        // Call original and return its return value
        return fn.apply(this, args);
    };
    // Set up the count
    newfn.count = 0;
    // Ensure the new function's `length` matches the original
    // (in case you have anything relying on it)
    Object.defineProperty(newfn, "length", {
        value: fn.length,
        configurable: true,
    });
    // Return the new function
    return newfn;
}

function square(a) {
    console.log(a);
    return a * a;
}

square = addCounter(square);
console.log(square(5));
console.log(`square.count = ${square.count}`);
console.log(square(1));
console.log(`square.count = ${square.count}`);
console.log(square(2));
console.log(`square.count = ${square.count}`);
console.log(square(3));
console.log(`square.count = ${square.count}`);
.as-console-wrapper {
    max-height: 100% !important;
}

您可能不会为 length 位而烦恼,代码在函数上查看 length 是不寻常的,但它在那里是彻底的。 (你必须使用defineProperty设置length。它是一个read-only属性,但它是可配置的,所以我们可以重新定义它。)

只是为了完整性:如果在您更新之前任何东西已经获取了对该函数的引用,那么通过其他引用的调用将不会被计算在内。但这是不寻常的,希望你不会碰巧有代码来做这件事。你可以 运行 进入其中的一个地方是,如果你正在使用 CommonJS 模块(直接使用,或者因为你的捆绑器将 JavaScript 标准模块语法转换为 CommonJS,就像某些人所做的那样)并且你在你之前导出它替换它(这似乎不太可能)。出现问题的原因是对于 CommonJS 模块,导出的是函数引用的副本。 不是本地使用的标准JavaScript模块(import/export)的问题,因为导入是原始导出的实时绑定,所以以上就可以正常工作了。