Domanda

Ho una funzione, a () , che voglio sovrascrivere, ma ho anche l'originale a () eseguito in un ordine a seconda del contesto. Ad esempio, a volte quando sto generando una pagina, voglio sovrascrivere in questo modo:

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

e talvolta come questo:

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

Come posso ottenere quel original_a () dall'interno del a () ? È anche possibile?

Per favore, non suggerire alternative all'over-riding in questo modo, ne conosco molte. Sto chiedendo questo in modo specifico.

È stato utile?

Soluzione

Potresti fare qualcosa del genere:

var a = (function() {
    var original_a = a;

    if (condition) {
        return function() {
            new_code();
            original_a();
        }
    } else {
        return function() {
            original_a();
            other_new_code();
        }
    }
})();

Dichiarare original_a all'interno di una funzione anonima gli impedisce di ingombrare lo spazio dei nomi globale, ma è disponibile nelle funzioni interne.

Come Nerdmaster menzionato nei commenti, assicurati di includere il () alla fine. Si desidera chiamare la funzione esterna e memorizzare il risultato (una delle due funzioni interne) in a , non memorizzare la funzione esterna stessa in a .

Altri suggerimenti

Il Modello proxy potrebbe aiutarti:

(function() {
    // log all calls to setArray
    var proxied = jQuery.fn.setArray;
    jQuery.fn.setArray = function() {
        console.log( this, arguments );
        return proxied.apply( this, arguments );
    };
})();
  

Quanto sopra racchiude il suo codice in una funzione per nascondere la variabile "proxy". Salva il metodo setArray di jQuery in una chiusura e lo sovrascrive. Il proxy quindi registra tutte le chiamate al metodo e delega la chiamata all'originale. L'uso di apply (questo, argomenti) garantisce che il chiamante non sarà in grado di notare la differenza tra il metodo originale e il metodo proxy.

Grazie ragazzi, il modello proxy ha davvero aiutato ..... In realtà volevo chiamare una funzione globale ... In alcune pagine devo fare alcuni controlli. Quindi ho fatto quanto segue.

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

Questo mi ha davvero aiutato

Puoi sovrascrivere una funzione usando un costrutto come:

function override(f, g) {
    return function() {
        return g(f);
    };
}

Ad esempio:

 a = override(a, function(original_a) {
      if (condition) { new_code(); original_a(); }
      else { original_a(); other_new_code(); }
 });

Modifica: risolto un errore di battitura.

Passaggio di argomenti arbitrari:

a = override(a, function(original_a) {
    if (condition) { new_code(); original_a.apply(this, arguments) ; }
    else { original_a.apply(this, arguments); other_new_code(); }
});

Gli esempi sopra non applicano correttamente this o passano argomenti correttamente alla funzione di override. Underscore _.wrap () racchiude le funzioni esistenti, applica this e passa correttamente argomenti . Vedi: http://underscorejs.org/#wrap

La risposta che @Matthew Crumley fornisce sta usando le espressioni di funzione immediatamente invocate, per chiudere la vecchia funzione 'a' nel contesto di esecuzione della funzione restituita. Penso che questa sia stata la risposta migliore, ma personalmente preferirei passare la funzione "a" come argomento all'IIFE. Penso che sia più comprensibile.

   var a = (function(original_a) {
        if (condition) {
            return function() {
                new_code();
                original_a();
            }
        } else {
            return function() {
                original_a();
                other_new_code();
            }
        }
    })(a);

Avevo scritto del codice da qualcun altro e volevo aggiungere una riga a una funzione che non riuscivo a trovare nel codice. Quindi, come soluzione alternativa, ho voluto sostituirlo.

Nessuna delle soluzioni ha funzionato per me.

Ecco cosa ha funzionato nel mio caso:

if (typeof originalFunction === "undefined") {
    originalFunction = targetFunction;
    targetFunction = function(x, y) {
        //Your code
        originalFunction(a, b);
        //Your Code
    };  
}

Ho creato un piccolo aiuto per uno scenario simile perché spesso avevo bisogno di sovrascrivere le funzioni di diverse librerie. Questo aiuto accetta uno "spazio dei nomi" (il contenitore della funzione), il nome della funzione e la funzione di sostituzione. Sostituirà la funzione originale nello spazio dei nomi indicato con quella nuova.

La nuova funzione accetta la funzione originale come primo argomento e gli argomenti delle funzioni originali come il resto. Conserverà il contesto ogni volta. Supporta anche funzioni void e non-void.

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

Utilizzo ad esempio con Bootstrap:

overrideFunction($.fn.popover.Constructor.prototype, 'leave', function(baseFn, obj) {
    // ... do stuff before base call
    baseFn(obj);
    // ... do stuff after base call
});

Tuttavia non ho creato alcun test delle prestazioni. Può eventualmente aggiungere un sovraccarico indesiderato che può o non può essere un grosso problema, a seconda degli scenari.

A mio avviso, le risposte migliori non sono leggibili / gestibili e le altre risposte non legano correttamente il contesto. Ecco una soluzione leggibile che utilizza la sintassi ES6 per risolvere entrambi questi problemi.

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

Quindi la mia risposta è risultata essere una soluzione che mi consente di utilizzare la variabile _this che punta all'oggetto originale. Creo una nuova istanza di un "quadrato" tuttavia odiavo il modo in cui "Square" generato la sua dimensione. Ho pensato che dovrebbe seguire le mie esigenze specifiche. Tuttavia, per fare ciò avevo bisogno che il quadrato avesse un aggiornamento "GetSize" funzione con gli interni di quella funzione chiamando altre funzioni già esistenti nel quadrato come this.height, this.GetVolume (). Ma per farlo avevo bisogno di farlo senza alcun trucco folle. Quindi ecco la mia soluzione.

Qualche altro inizializzatore di oggetti o funzione di supporto.

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

Funzione nell'altro oggetto.

updateToolbarButtons = function(viewer) {
  var _viewer = viewer;
  return function(width, height){ 
blah blah black sheep I can refer to this.anything();
}
};
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top