Pregunta

Tengo una función, a () , que quiero anular, pero también hago que el a () original se realice en un orden según el contexto. Por ejemplo, a veces, cuando estoy generando una página, quiero anular así:

function a() {
    new_code();
    original_a();
}

y a veces así:

function a() {
    original_a();
    other_new_code();
}

¿Cómo obtengo ese original_a () desde dentro del a () dominante? ¿Es posible?

Por favor, no sugiera alternativas para anular de esta manera, conozco muchas. Estoy preguntando sobre esta manera específicamente.

¿Fue útil?

Solución

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 satura el espacio de nombres global, pero está disponible en las funciones internas.

Al igual que Nerdmaster mencionado en los comentarios, asegúrese 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 .

Otros consejos

El Patrón de proxy podría ayudarlo:

(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. Luego, el proxy registra todas las llamadas al método y delega la llamada al original. El uso de apply (esto, argumentos) garantiza que la persona que llama no podrá notar la diferencia entre el método original y el proxy.

Gracias chicos, el patrón proxy realmente ayudó ..... En realidad quería llamar a una función global foo ... En ciertas páginas necesito hacer algunos controles. 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);
    }
};

Gracias, esto realmente me ayudó

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(); }
 });

Editar: se corrigió un error tipográfico.

Pasar 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(); }
});

Los ejemplos anteriores no aplican correctamente this o pasan argumentos correctamente a la función de anulación. Subrayar _.wrap () ajusta las funciones existentes, aplica this y pasa argumentos correctamente. Ver: http://underscorejs.org/#wrap

La respuesta que proporciona @Matthew Crumley es hacer uso de las expresiones de función invocadas inmediatamente, para cerrar la función 'a' anterior 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 a 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);

Tenía otro 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 anularlo.

Sin embargo, ninguna de las soluciones funcionó para mí.

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
    };  
}

He creado un pequeño ayudante para un escenario similar porque a menudo necesitaba anular funciones de varias bibliotecas. Este asistente 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 la nueva.

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
});

Sin embargo, 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.

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 utiliza la sintaxis de ES6 para resolver estos dos problemas.

const orginial = someObject.foo;
someObject.foo = function() {
  if (condition) orginial.bind(this)(...arguments);
};

Entonces, mi respuesta terminó siendo una solución que me permite usar la _esta variable apuntando al objeto original. Creo una nueva instancia de un "Cuadrado" Sin embargo, odiaba la forma en que la "Plaza" generó su tamaño. Pensé que debería seguir mis necesidades específicas. Sin embargo, para hacerlo, necesitaba que el cuadrado tuviera un "GetSize" actualizado. funciona con los elementos internos de esa función llamando a otras funciones ya existentes en el cuadrado como this.height, this.GetVolume (). Pero para hacerlo necesitaba hacer esto sin ningún truco loco. Así que aquí está mi solución.

Alguna otra inicializador de objetos o función auxiliar.

this.viewer = new Autodesk.Viewing.Private.GuiViewer3D(
  this.viewerContainer)
var viewer = this.viewer;
viewer.updateToolbarButtons =  this.updateToolbarButtons(viewer);

Función en el otro objeto.

updateToolbarButtons = function(viewer) {
  var _viewer = viewer;
  return function(width, height){ 
blah blah black sheep I can refer to this.anything();
}
};
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top