tipos - Anulando una función de JavaScript al hacer referencia al original
para terminar las instrucciones en javascript se utiliza (10)
Creé un pequeño ayudante para un escenario similar porque a menudo necesitaba anular funciones de varias bibliotecas. Este ayudante acepta un "espacio de nombres" (el contenedor de funciones), el nombre de la función y la función de anulación. Reemplazará la función original en el espacio de nombres referido con el nuevo.
La nueva función acepta la función original como primer argumento, y los argumentos de las funciones originales como el resto. Preservará el contexto cada vez. También admite funciones nulas y no nulas.
function overrideFunction(namespace, baseFuncName, func) {
var originalFn = namespace[baseFuncName];
namespace[baseFuncName] = function () {
return func.apply(this, [originalFn.bind(this)].concat(Array.prototype.slice.call(arguments, 0)));
};
}
Uso, por ejemplo, con Bootstrap:
overrideFunction($.fn.popover.Constructor.prototype, ''leave'', function(baseFn, obj) {
// ... do stuff before base call
baseFn(obj);
// ... do stuff after base call
});
Aunque no creé ninguna prueba de rendimiento. Posiblemente puede agregar algunos gastos indirectos no deseados que pueden o no ser un gran problema, dependiendo de los escenarios.
Tengo una función, a()
, que quiero sobrescribir, pero también hago que el a a()
original se realice en un orden según el contexto. Por ejemplo, a veces, cuando estoy generando una página, quiero sobrescribirlo así:
function a() {
new_code();
original_a();
}
y a veces así:
function a() {
original_a();
other_new_code();
}
¿Cómo obtengo ese original_a()
dentro del over-riding a()
? ¿Es posible?
Por favor, no sugiera alternativas a la superación de esta manera, sé de muchos. Estoy preguntando acerca de esta manera específicamente.
El patrón de Proxy puede ayudarlo a:
(function() {
// log all calls to setArray
var proxied = jQuery.fn.setArray;
jQuery.fn.setArray = function() {
console.log( this, arguments );
return proxied.apply( this, arguments );
};
})();
Lo anterior envuelve su código en una función para ocultar la variable "proxy". Guarda el método setArray de jQuery en un cierre y lo sobrescribe. El proxy registra todas las llamadas al método y delega la llamada al original. El uso de apply (this, arguments) garantiza que el que llama no podrá notar la diferencia entre el método original y el proxy.
En mi opinión, las respuestas principales no son legibles / mantenibles, y las otras respuestas no vinculan adecuadamente el contexto. Aquí hay una solución legible que usa la sintaxis ES6 para resolver ambos problemas.
const orginial = someObject.foo;
someObject.foo = function() {
if (condition) orginial.bind(this)(...arguments);
};
Gracias a todos, el patrón de proxy realmente me ayudó ... De hecho, quería llamar a un foo de función global ... En ciertas páginas, necesito hacer algunas comprobaciones. Entonces hice lo siguiente.
//Saving the original func
var org_foo = window.foo;
//Assigning proxy fucnc
window.foo = function(args){
//Performing checks
if(checkCondition(args)){
//Calling original funcs
org_foo(args);
}
};
Esto realmente me ayudó
La respuesta que proporciona @Matthew Crumley es hacer uso de las expresiones de función invocadas inmediatamente para cerrar la antigua función ''a'' en el contexto de ejecución de la función devuelta. Creo que esta fue la mejor respuesta, pero personalmente, preferiría pasar la función ''a'' como argumento para IIFE. Creo que es más comprensible.
var a = (function(original_a) {
if (condition) {
return function() {
new_code();
original_a();
}
} else {
return function() {
original_a();
other_new_code();
}
}
})(a);
Los ejemplos anteriores no aplican correctamente this
ni pasan los arguments
correctamente a la anulación de la función. Subrayar _.wrap () ajusta las funciones existentes, aplica this
y pasa los arguments
correctamente. Ver: http://underscorejs.org/#wrap
Pasando argumentos arbitrarios:
a = override(a, function(original_a) {
if (condition) { new_code(); original_a.apply(this, arguments) ; }
else { original_a.apply(this, arguments); other_new_code(); }
});
Podrías hacer algo como esto:
var a = (function() {
var original_a = a;
if (condition) {
return function() {
new_code();
original_a();
}
} else {
return function() {
original_a();
other_new_code();
}
}
})();
Declarar original_a
dentro de una función anónima evita que ocupe el espacio de nombres global, pero está disponible en las funciones internas.
Como Nerdmaster mencionado en los comentarios, asegúrate de incluir el ()
al final. Desea llamar a la función externa y almacenar el resultado (una de las dos funciones internas) en a
, no almacenar la función externa en a
.
Puede anular una función usando una construcción como:
function override(f, g) {
return function() {
return g(f);
}:
}
Por ejemplo:
a = override(a, function(original_a) {
if (condition) { new_code(); original_a(); }
else { original_a(); other_new_code(); }
});
Tenía un código escrito por otra persona y quería agregar una línea a una función que no pude encontrar en el código. Entonces, como solución, quería anularla.
Ninguna de las soluciones funcionó para mí, sin embargo.
Esto es lo que funcionó en mi caso:
if (typeof originalFunction === "undefined") {
originalFunction = targetFunction;
targetFunction = function(x, y) {
//Your code
originalFunction(a, b);
//Your Code
};
}