2012-06-27 15 views
15

Devo attivare la barra delle funzioni() ogni volta che si attiva la funzione foo(). Non ho controllo sulla funzione foo o se cambierà in futuro. Ho questa situazione regolarmente (e lo odio).Aggiunge codice alla fine di una funzione esistente

Ho scritto questa funzione per aggiungere il mio codice alla fine della funzione foo:

function appendToFunction(fn,code){ 
if(typeof fn == 'function'){ 
    var fnCode = fn.toString() ; 
    fnCode = fnCode.replace(/\}$/,code+"\n}") ; 
    window.eval(fnCode);     // Global scope 
    return true ; 
} 
else{ 
    return false ; 
} 
} 

esempio:

appendToFunction(foo,"bar();"); 

Questa mi sembra una pessima idea - ma funziona. Qualcuno può indicarmi una direzione migliore (più sicura) per favore.

MODIFICA: foo non è una funzione specifica, ma molte funzioni che finiscono con. Non cambiano dinamicamente nella pagina. Ma possono essere cambiati (ad esempio richieste di convalida del modulo) di volta in volta.

Soluzione: Ho optato per una versione modificata della risposta di Adam. Non è perfetto, ma è migliore di quello che avevo:

var oldFoo = foo ; 
foo = function(){ 
     var result = oldFoo.apply(this, arguments); 
     bar(); 
     return result ; 
} 

NB. Prestare attenzione a alcune funzioni native in IE6/7 che non dispongono di un metodo .apply().

+0

possibile duplicato [Aggiunta codice a una funzione JavaScript programatically] (http://stackoverflow.com/questions/9134686/adding-code-to- a-javascript-function-programatically) –

risposta

24

si può semplicemente ignorare foo con una funzione personalizzata che chiama l'originale.

E.g.

var old_foo = foo; 
foo = function() { 
    old_foo(); 
    bar(); 
} 

Si dovrebbe anche passare alcun argomento foo prende in via la funzione di sostituzione.

+0

Più semplice e un po 'più sicuro del mio. Con le modifiche per 'arguments' e' return' questo probabilmente funzionerebbe nella maggior parte dei casi. – ColBeseder

+0

Questa soluzione causa un sovraccarico dello stack per me. Se si verifica lo stesso, la soluzione di xdazz in basso ha funzionato per me. – Observer

3

Hmm, questo mi riguarda pure, lei ha detto che

ho questa situazione regolarmente (e io odio).

Ti spiace se chiedo in quale scenario questo continua a verificarsi? È su scala aziendale o nell'ambito di un progetto personale? Hai chiaramente la testa alle spalle e sai che quello che stai facendo è fuori dall'ordinario, quindi mi chiedo se c'è una soluzione alternativa.

La ragione per cui lo chiedo è; questo approccio potrebbe potenzialmente aprire una scatola di problemi. Cosa succede se, ad esempio, foo non riesce o se foo restituisce un valore a metà valutazione? Semplicemente aggiungendo bar alla funzione effettiva non garantisce che verrà eseguito. D'altra parte, supponiamo che sia più probabilmente da eseguire, ma secondo me non è un buon approccio.

Avete considerato di rivedere la funzione foo? So che potrebbe sembrare una domanda sciocca, ma potrebbe valerne la pena se incontri problemi simili in tutto il mondo. Se si desidera mantenere le cose astratte si può adottare un approccio "event handler", in base al quale foo attiva un evento su window, che a sua volta innesca lo bar, questo potrebbe funzionare nel tuo caso.

In alternativa, se si conosce che cos'è foo e che cosa fa, è possibile collegarsi al suo prototipo se si tratta di un oggetto, quindi modificare il codice in modo appropriato. Tuttavia, hai menzionato che questa funzione è aperta a modifiche, il che potrebbe rendere ridondante questa opzione, ma è comunque una soluzione possibile.

+0

È su una scala (multi) aziendale e non ho controllo sulla funzione 'pippo'. Spesso ci sono altre soluzioni (come setTimeout per controllare i risultati della funzione). Ma penso che l'attivazione di un evento sulla finestra suona come un leggero miglioramento di quello che ho. – ColBeseder

6
function extend(fn,code){ 
    return function(){ 
    fn.apply(fn,arguments) 
    code.apply(fn,argumnets) 
    } 
} 

e usarlo in questo modo:

function appendToFunction(fn,code){ 
    if(typeof fn == 'function'){ 
     var fnCode = fn.toString() ; 
     fnCode = fnCode.replace(/\}$/,code+"\n}") ; 
     window.eval(fnCode);     // Global scope 
     return true ; 
    } 
    else{ 
     return false ; 
    } 
} 

appendToFunction = extend(appendToFunction,function(){/*some code*/}); 

questo vi darà lo stesso "questo" in entrambe le funzioni

6

Si potrebbe fare qualcosa di simile: THE DEMO.

function foo() { 
console.log('foo'); 
} 

function appendToFunction(fn, callback) { 
    window[fn] = (function(fn){ 
    return function() { 
     fn(); 
     callback(); 
    } 
}(window[fn])); 
} 

appendToFunction('foo', function(){console.log('appended!')}); 

foo(); 
1

È possibile aggiungere o anteporre qualche nuovo codice per una funzione esistente solo fusione li utilizzano per esempio:

function mergeFunctions(function1, function2, instance1, instance2, numberOfArgumentsToPassToFunc1) { 
    return function() { 
     var _arguments = Array.prototype.slice.apply(arguments); 
     var _arguments1 = _arguments.slice(0, numberOfArgumentsToPassToFunc1); 
     var _arguments2 = _arguments.slice(numberOfArgumentsToPassToFunc1); 
     var that = this; 
     (function(function1, function2) { 
      if (typeof function1 == "function") { 
       if (typeof instance1 != "undefined") { 
        function1.apply(instance1, _arguments1); 
       } 
       else if (that == window) { 
        function1.apply(function1, _arguments1); 
       } 
       else { 
        var compare = mergeFunctions(function(){}, function(){}); 
        if (that.toString() == compare.toString()) { 
         function1.apply(function1, _arguments1); 
        } 
        else { 
         function1.apply(that, _arguments1); 
        } 
       } 
      } 
      if (typeof function2 == "function") { 
       if (typeof instance2 != "undefined") { 
        function2.apply(instance2, _arguments2); 
       } 
       else if (that == window) { 
        function2.apply(function2, _arguments2); 
       } 
       else { 
        var compare = mergeFunctions(function(){}, function(){}); 
        if (that.toString() == compare.toString()) { 
         function2.apply(function2, _arguments2); 
        } 
        else { 
         function2.apply(that, _arguments2); 
        } 
       } 
      } 
     })(function1, function2); 
    } 
} 



Un esempio di base sarebbe il seguente:

// Original function: 
var someFunction = function(){ 
    console.log("original content"); 
}; 

// Prepend new code: 
// -------------------------------------------------------- 
someFunction = mergeFunctions(function() { 
    console.log("--- prepended code"); 
}, someFunction); 

// Testing: 
someFunction(); 

// Outout: 
// [Log] --- prepended code 
// [Log] original content 


// Append new code: 
// -------------------------------------------------------- 
someFunction = mergeFunctions(someFunction, function() { 
    console.log("appended code"); 
}); 

// Testing: 
someFunction(); 

// Output: 
// [Log] --- prepended code 
// [Log] original content 
// [Log] appended code 


Nota che la funzione di unione tenta di applicare il previsto "questo" alle parti unite, altrimenti si può semplicemente passare il voluto "questo" a loro, così come è possibile gestire gli argomenti relativi.
Un più generale esempio potrebbe essere il seguente:

function firstPart(a, b) { 
    console.log("--- first part"); 
    console.log("'this' here is:"); 
    console.log(this.name); 
    console.log("a: "+a); 
    console.log("b: "+b); 
} 

function MyObject() { 
    this.x = "x property of MyObject"; 
} 

MyObject.prototype.secondPart = function (y) { 
    console.log(""); 
    console.log("--- second part"); 
    console.log("'this' here is:"); 
    console.log(this.name); 
    this.x = y; 
    console.log("x: "+this.x); 
} 

MyObject.prototype.merged = mergeFunctions(firstPart, MyObject.prototype.secondPart, firstPart, MyObject, 2); 

// Testing 
var test = new MyObject(); 
test.merged("a parameter", "b parameter", "x parameter overrides x property of MyObject"); 

// Console output: 
// [Log] --- first part 
// [Log] 'this' here is: 
// [Log] firstPart 
// [Log] a: a parameter 
// [Log] b: b parameter 
// [Log] 
// [Log] --- second part 
// [Log] 'this' here is: 
// [Log] MyObject 
// [Log] x: x parameter overrides x property of MyObject 
Problemi correlati