Чтобы узнать об использовании WeakMap
, я придумал следующий пример для отслеживания вызовов функций:
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
Какой был бы более чистый способ реализовать это, так как мне нужно использовать псевдонимы функций туда и обратно, например, от add
к _add
и обратно к add
. Кроме того, является ли вышеуказанное законным использованием Weakmap?
Использование WeakMap довольно странное — как вы заметили, если вы хотите что-то с ним посмотреть с помощью функций, вам нужно хранить эти функции в переменных, которые отделены от функции, вызываемой счетчиком. Это делает вещи неудобными, и WeakMap, похоже, не имеет чистой выгоды по сравнению с простым объектом, если у вас нет конфликтов имен функций.
Если это разрешено тем, что вы ищете, вы можете передать другой аргумент countFunctionInvocations
, указывающий имя, что позволит вам передать (краткую, анонимную) функцию стрелки.
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);
Additionally, is the above a legitimate usage of Weakmap?
Я имею в виду, что его можно было бы использовать, но, как мы заметили, неудобно иметь две отдельные ссылки на функцию — одна из них является базовой функцией, а другая — преобразованной с помощью countFunctionInvocations
.
Тем не менее, это, безусловно, законное использование WeakMap над картой, потому что это позволяет функции (и количеству ее вызовов) собирать мусор, когда ничто другое не может ссылаться на нее.
Я предполагаю, что другим вариантом будет возвращаемая функция, которая будет помещена в карту, чтобы у вас был только один идентификатор снаружи, но для этого потребуется function
или второй аргумент, чтобы указать имя функции, иначе внутри countFunctionInvocations
увидит только анонимную функцию без имени.
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
Раньше это был один из немногих способов для классов иметь хорошую конфиденциальность для свойств экземпляра с помощью замыкания, но теперь это изменилось, когда частные свойства стали опцией. (Она обычно используется в транспилированном коде с Babel). Кроме этого, я никогда не сталкивался с ситуацией, когда писал свой собственный код, где WeakMap казался бы правильным решением, но это отчасти результат моего личного стиля, и я бы не стал этого делать. исключают возможность того, что он никогда не окажется подходящим инструментом для работы в будущем.
спасибо за все это. Является ли приведенное выше натяжкой для использования типа данных
WeakMap
? Есть ли для него какое-либо последовательное/законное использование, или оно довольно редко встречается в производственных программах?