Quería crear una función a la que pueda agregar acciones más adelante. Intenté esto:
Function.prototype.appendAction = function(action) { let _ogFn = this return function(...args) { _ogFn(...args) action() } } function a() { console.log("foo") } a() a = a.appendAction(() => console.log("bar")) a()Esto funciona , pero ¿cómo puedo hacer que cambie la función automáticamente? Quiero que funcione así:
a() a.appendAction(() => console.log("bar")) //note it doesn't have the "a = " a() //changed functionDependiendo de su escenario, podría crear un decorador de funciones. Esto significaría definir una función (por ejemplo fnMod ) que acepte una función fn y devuelva una versión decorada que ejecute algunos ganchos antes y después .
const a = fnMod(() => { console.log("foo"); }); a(); a.appendAction(() => console.log("bar")); a(); const john = { name: "John Doe", age: 42, greet: fnMod(function () { console.log(`I'm ${this.name}.`); // <- uses `this` so use a normal function }) } john.greet.prependAction((name) => { console.log(`Hi ${name}!`); // <- does not use `this` so both a normal function }); // or arrow function will work fine john.greet.appendAction(function () { console.log(`I'm ${this.age} years old.`); }); john.greet("Jane"); function fnMod(fn) { const before = []; const after = []; function hookable(...args) { before.forEach(fn => fn.apply(this, args)); const result = fn.apply(this, args); after.forEach(fn => fn.apply(this, args)); return result; }; hookable.prependAction = (fn) => { before.unshift(fn); } hookable.appendAction = (fn) => { after.push(fn); } return hookable; } Es posible que desee modificarlo a su gusto. Actualmente, tanto this como todos los argumentos pasados a la función decorada se reenvían a todos los ganchos, lo que podría o no ser deseable.
Si solo quieres llamarlo inmediatamente:
Function.prototype.appendAction = function(action) { let _ogFn = this return (function(...args) { _ogFn(...args) action() })() } function a() { console.log("foo") } a.appendAction(() => console.log("bar"))Ese es el patrón de expresión de función inmediatamente invocada (IIFE)
Para sus propósitos, podría usar eval :
Primero, tome la entrada del usuario como sea que la esté manejando y analícela como una cadena.
Luego usa eval así:
let userInput = 'console.log("hello world")'; const callUserFunction = (action) => { eval(`function fn(){${action}}`); fn(); } callUserFunction(userInput);Tenga en cuenta que permitir que un usuario escriba o JS es un riesgo de seguridad, que puede abrir las puertas a todo tipo de ataques, por lo que en la mayoría de los escenarios, desaconsejaría hacerlo.