Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

177
Vistas
"prefix" function calls by specific function call

I have some JavaScript code consisting of several functions that may or may not call each other. Here is an example:

function a(x)    { return 2*x; }
function b(x, y) { return a(y) + x; }
function c()     { return b(1, 2); }

I have a special function that takes a function and its arguments and returns the computed value (among other things, see explanation below):

function pre(f, ...args) { return f(...args); }

Is it possible to "prefix" all function calls by this function WITHOUT needing to modify/reassign the functions?

I.e. the call pre(c); should behave as if the functions were defined like this:

function a(x) { return 2*x; }
function b(x, y) { return pre(a, y) + x; }
function c() { return pre(b, 1, 2); }
  • Maybe we can define an object that overrides "standard" function call behaviour, so that it intercepts the call and prefixes it with this function?
  • If this requires the presence of certain objects, or all functions to be member of a certain object, that is alright.
  • If this requires a function call to be written differently (not just c();), that is alright.

Use case:

I have a (Java) program in which an end-user can define JavaScript functions. This program reads some external data and calls these JavaScript functions on it. Finally, some result from these function calls will be given back to the end-user.

The user-defined functions are side-effect free (the program makes sure of that); they are pure calculation functions. Because of that, it suffices to call each function mostly once - they will always give the same output for identical input. So I wanted to implement a caching mechanism inside pre like e.g. this:

var cache = new Map();
function pre(f, ...args) {
    var array = new Array(args.length + 1);
    array[0] = f.name;
    for (var i = 0; i < args.length; i++) {
        array[i+1] = args[i];
    }
    var stringified = JSON.stringify(array);
    if (cache.has(stringified)) {
        return cache.get(stringified);
    }
    else {
        var calc = Object.freeze(f(...args));
        cache.set(stringified, calc);
        return calc;
    }
}

I currently implemented it so that I just modify all user-defined functions (which are given as strings, so I manipulate strings) to contain the pre call. But I'm interested in a more elegant solution - a solution that does not require code modification - and if there is, I'm sure the knowledge of that solution can help in many situations.

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

If I'm understanding you correctly, you want to be able to define functions like this:

function a(x)    { return 2*x; }
function b(x, y) { return a(y) + x; }
function c()     { return b(1, 2); }

and then after defining them (after the functions and the a, b, and c bindings for them exist), intercept all of the calls to a, b, or c (including the ones inside b and c) without reassigning the a, b, or c identifiers (more formally, bindings).

You can't do that. It would require reaching into b (for instance) and changing which a binding b uses to find and call the function assigned to a. You can change the value of the a binding that b uses (e.g., which function a refers to) by reassigning it, but not which a binding b uses.

Just for the sake of any lurkers who want to know how to do it with reassignment, here's how, but the OP has specifically said they don't want to do this:

var cache = new Map();
function pre(f, ...args) {
    var array = new Array(args.length + 1);
    array[0] = f.name;
    for (var i = 0; i < args.length; i++) {
        array[i+1] = args[i];
    }
    var stringified = JSON.stringify(array);
    if (cache.has(stringified)) {
        return cache.get(stringified);
    }
    else {
        var calc = Object.freeze(f(...args));
        cache.set(stringified, calc);
        return calc;
    }
}

// Doesn't handle `this` because the OP didn't need to and the
// `pre` function would have to be modified to handle it
function wrap(original) {
    return (...args) => pre(original, ...args);
}


function a(x) {
    console.log(`a called with`, x);
    return 2 * x;
}
function b(x, y) {
    console.log(`b called with`, x, y);
    return a(y) + x;
}
function c() {
    console.log(`c called`);
    return b(1, 2);
}

a = wrap(a);
b = wrap(b);
c = wrap(c);
console.log(`First call:`);
console.log(c());
console.log(`Second call:`);
console.log(c());


In a comment you've said:

More precisely, I want to know if there is a level between "what b(1, 2) does" (the function itself) and the ... thing ... (the interpreter?) that says "now call that function". And if there is a level in-between, I want to know if that can be modified.

The only level in-between in a standard JavaScript environment is the lexical environment object that holds the a, b, and c bindings, which is what we'd be changing by reassigning them. There's nothing else we can do to intercept/adjust those function calls.

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda