An effective method that avoids using a proxy involves using a general implementation of an around
method-modifier. This can be viewed as a specialized form of function wrapping.
This modifier takes two functions, proceed
and handler
, along with a target
-object as its three parameters. It then generates a function that will return the result of the handler
function. The handler
function is executed within the context of the (possibly) provided target
, receiving both the proceed
function and its own reference as well as the arguments array of the modified function.
Using this modifier, the OP could achieve the desired outcome by modifying, for example, the sort
method of an array instance like so...
const arr = [2, 1];
// assigning the specifically modified `sort` of the array instance.
arr.sort = around(arr.sort, notifyAboutFinishedTask, arr);
... where notifyAboutFinishedTask
represents the handler
function that fulfills the requirements outlined by the OP...
"... only one notification after an array sort"
... Sample code ...
// Implementation of `sort`-specific `around` handler.
function notifyAboutFinishedTask(proceed, handler, args) {
const arr = this;
// Original task execution.
proceed.apply(arr, args);
// Additional notification.
console.log('\narray sorted');
console.log('arr ...', arr);
console.log('arguments ...', args);
}
const arr = [2, 1];
console.log('unsorted arr ...', arr);
// Assigning the specifically modified `sort` of the array instance.
arr.sort = around(arr.sort, notifyAboutFinishedTask, arr);
// Sorting the array twice, once with a sort function and once without.
arr.sort();
arr.sort((a, b) => b - a);
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
// Implementation of an `around` modifier.
function around(proceed, handler, target) {
return function (...args) {
return handler.call(target ?? null, proceed, handler, args);
};
}
</script>