2010-01-21 21 views
7

Ho una strana domanda in cui ho bisogno di iniettare qualche javascript in un'altra funzione javascript. Sto usando un framework che è bloccato, quindi non posso cambiare la funzione esistente.Inject javascript in una funzione javascript

quello che ha è qualcosa di simile

funzione doSomething() { ...}

... ***

posso manipolare il *** (sopra) tuttavia non posso cambiare la funzione doSomething ... Invece ho bisogno di iniettare qualche riga di codice alla fine del codice doSomething.

Il motivo per cui ho bisogno di fare questo è che il framework personalizzato chiama doSomething() e questo si traduce in un ID restituito dal server che ho bisogno di estrarre. Questo ID viene fatto riferimento solo all'interno della funzione doSomething, quindi non posso prenderlo a meno che non si inietti codice a quella funzione (a meno che non mi sia sfuggito qualcosa).

C'è un modo per farlo?

+3

Come si blocca la funzione? – Lazarus

+0

Possibile duplicato di [C'è un modo per racchiudere tutti i metodi JavaScript con una funzione?] (Http://stackoverflow.com/questions/3919134/is-there-a-way-to-wrap-all-javascript-methods- with-a-function) –

risposta

0

Le funzioni sono valori di prima classe in Javascript, il che significa che è possibile memorizzarle in variabili (e infatti, dichiarare che una funzione denominata sta essenzialmente assegnando una funzione anonima a una variabile).

Si dovrebbe essere in grado di fare qualcosa del genere:

function doSomething() { ... } 

var oldVersionOfFunc = doSomething; 
doSomething = function() { 

    var retVal = oldVersionOfFunc.apply(oldVersionOfFunc, args); 

    // your added code here 

    return retVal; 
} 

(Ma, potrei sbagliarmi mio javascript è un po 'arrugginito,..))

+1

Se ho ottenuto la domanda giusta, non sarà di aiuto in questo caso, poiché il problema è estrarre il valore di una variabile locale a cui fa riferimento solo "doSomething". E la nuova versione di 'doSomething' non può fare riferimento a variabili all'interno di quella vecchia. –

5

Alias ​​IT.

var oldDoSomething = doSomething; 
doSomething = function() { 
    // Do what you need to do. 
    return oldDoSomething.apply(oldDoSomething, arguments); 
} 
+0

ha bisogno di accedere a una variabile con ambito alla funzione originale – Matt

0

non posso cambiare la funzione doSomething ... Invece ho bisogno di iniettare qualche modo un paio di righe di codice nella parte finale del codice doSomething

Iniezione di poche righe in fine del codice doSomething suona come modificare la funzione doSomething, per me. Penso, sfortunatamente, che sei fregato.

(io sono un po 'confuso su tutto questo, ma penso che le funzioni sono come le persone che si preoccupano di queste cose implementano information hiding in JavaScript, proprio perché non è possibile accedere al proprio ambito di applicazione al di fuori di loro.)

1
function doSomething() { ... } 
var oldVersionOfFunc = doSomething; 
doSomething = function() { 
    var retVal = oldVersionOfFunc.apply(oldVersionOfFunc, args); 
    // your added code here 
    return retVal; 
} 

Questo sembra provocare un errore (Troppo ricorsione)

function doSomething(){ document.write('Test'); return 45; } 
var code = 'myDoSomething = ' + doSomething + '; function doSomething() { var id = myDoSomething(); document.write("Test 2"); return id; }'; 
eval(code) 
doSomething(); 

Questo funziona per me, anche se è brutto.

2

Non sono sicuro di cosa intendi per "bloccato" - JavaScript è interpretato dal tuo browser. Anche se è stato minimizzato o codificato, è comunque possibile copiare l'origine di tale funzione dall'origine della pagina di script. A quel punto, riassegni la funzione originale a uno dei tuoi progetti, che contiene il codice copiato più il tuo.

var id; 
var myFunction = function() { 
    // code copied from their source, which contains the variable needed 

    // insert your own code, such as for copying the needed value 
    id = theirIDvalue; 

    // return the value as originally designed by the function 
    return theirValue; 
}; 

theirObject.theirFunction = myFunction; 
3

Grazie per tutto il vostro feedback. Ogni risposta mi ha dato un indizio e come tale ho trovato la seguente soluzione.

<body> 
<script type="text/javascript"> 
    var val; 
    function doSomething(item1, item2) { 
     var id = 3; 
    } 
    function merge() { 
     var oScript = document.createElement("script"); 
     var oldDoSomething = doSomething.toString(); 
     oScript.language = "javascript"; 
     oScript.type = "text/javascript"; 
     var args = oldDoSomething.substring(oldDoSomething.indexOf("(") + 1, oldDoSomething.indexOf(")")); 
     var scr = oldDoSomething.substring(oldDoSomething.indexOf("{") + 1, oldDoSomething.lastIndexOf("}") - 1); 
     var newScript = "function doSomething(" + args + "){" + scr + " val = id; }"; 
     oScript.text = newScript; 
     document.getElementsByTagName('BODY').item(0).appendChild(oScript); 
    } 

    merge(); 

</script> 
<input type="button" onclick="doSomething();alert(val);" value="xx" /> 

+1

Una soluzione migliore (non richiede la manipolazione DOM, è puro Javascript): http://stackoverflow.com/a/9134757/39722 –

1

Alterare la funzione lavorando con le stringhe di codice sorgente può essere abbastanza semplice. Per farlo per un'istanza specifica, provare:

eval(doSomething.toString().replace(/}\s*$/, ' return id; $&'); 

Ora doSomething restituisce l'ID. Normalmente non sono un fan di eval, ma le normali tecniche aspect oriented programming non si applicano qui, a causa del requisito per l'accesso a una variabile locale.

Se doSomething restituisce già un valore, provare:

eval(doSomething.toString().replace(/}\s*$/, ' window.someID = id; $&'); 

di trasformare questo in una funzione, abbiamo bisogno di rendere il codice valutare in ambito globale:

function insertCode(func, replacer, pattern) { 
    var newFunc = func.toString().replace(pattern, replacer); 
    with (window) { 
     eval(newFunc); 
    } 
} 
function after(func, code) { 
    return insertCode(func, function (old) { code + old }, /}\s*$/); 
} 
... 
after(doSomething, 'return id;'); 

Se si vuole riscrivere metodi e funzioni anonimi legati a variabili, modifica insertCodeBefore a:

function insertCode(funcName, replacer, pattern) { 
    var newFunc = eval('window.' + funcName).toString().replace(pattern, replacer); 
    eval('window.' + funcName + '=' + newFunc); 
} 
... 
function Foo() {} 
Foo.prototype.bar = function() { var secret=0x09F91102; } 
... 
after('doSomething', 'return id;'); 
after('Foo.prototype.bar', 'return secret;'); 

Nota il primo argomento delle funzioni sono ora stringhe. Possiamo definire altre funzioni:

function before(func, code) { 
    return insertCode(func, function (old) {old + code}, /^function\s+\w+\([^)]*\)\s+{/); 
} 
function around(func, beforeCode, afterCode) { 
    before(func, beforeCode); 
    after(func, afterCode); 
} 
+0

Questo non funzionerà nel caso generale perché la funzione può eseguire un ritorno in qualsiasi momento prima, quindi potrebbe non raggiungere il codice inserito. –