Para aprender sobre el uso de WeakMap , se me ocurrió el siguiente ejemplo para rastrear las invocaciones de funciones:
var map = new WeakMap(); function countFunctionInvocations(func) { return function(...args) { map.set(func, (map.get(func) || 0)+1); return func.apply(this, args); } }; const _add = (x,y) => x+y; const _inc = x => x+1; const add = countFunctionInvocations(_add); const inc = countFunctionInvocations(_inc); add(2,3); add(1,2); add(2,3); add(2,3); inc(inc(1)); console.log(map.get(_add), map.get(_inc)); // 4 2 ¿Cuál sería una forma más limpia de implementar esto, ya que tengo que alias las funciones de un lado a otro, por ejemplo, de add a _add y de regreso a add ? Además, ¿es lo anterior un uso legítimo de Weakmap?
El uso de WeakMap es bastante extraño: como ha notado, si desea buscar cosas con funciones, debe almacenar esas funciones en variables, que están separadas de la función invocada por conteo. Hace las cosas incómodas y un WeakMap no parece tener un beneficio neto sobre un objeto simple, siempre que no tenga colisiones de nombres de funciones.
Si esto está permitido por lo que está buscando, podría pasar otro argumento a countFunctionInvocations indicando el nombre, permitiéndole pasar una función de flecha (concisa, anónima).
const counts = {}; function countFunctionInvocations(name, func) { return function(...args) { counts[name] = (counts[name] ?? 0) + 1; console.log("called", name, counts[name]); return func.apply(this, args); } }; const add = countFunctionInvocations('add', (x,y) => x+y); const inc = countFunctionInvocations('inc', x => x + 1); add(2,3); add(1,2); add(2,3); add(2,3); inc(inc(1)); console.log(counts.add, counts.inc);Además, ¿es lo anterior un uso legítimo de Weakmap?
Quiero decir, podría usarse, pero como hemos notado, es incómodo tener dos referencias separadas a una función: una es la función base y otra es la transformada por countFunctionInvocations .
Dicho esto, este es sin duda un uso legítimo de WeakMap sobre un Map , porque permite que la función (y su recuento de invocaciones) se recopile como basura una vez que nada más pueda hacer referencia a ella.
Supongo que otra opción sería que la función devuelta sea la que se puso en el Mapa, de modo que solo tenga un identificador en el exterior, pero requeriría una function o un segundo argumento para indicar el nombre de la función, de lo contrario el interior de countFunctionInvocations solo vería una función anónima sin nombre.
const map = new WeakMap(); function countFunctionInvocations(func) { const fn = (...args) => { map.set(fn, (map.get(fn) || 0) + 1); // use returned function in Map return func.apply(this, args); // invoke passed function } return fn; }; const add = countFunctionInvocations(function add(x, y) { return x + y }); const inc = countFunctionInvocations(function inc(x) { return x + 1 }); add(2,3); add(1,2); add(2,3); add(2,3); inc(inc(1)); console.log(map.get(add), map.get(inc)); // 4 2