2010-01-21 29 views
7

Ich habe eine seltsame Frage, in der ich etwas Javascript in eine andere Javascript-Funktion injizieren muss. Ich verwende ein Framework, das gesperrt ist, so dass ich die bestehende Funktion nicht ändern kann.Injizieren Sie Javascript in eine JavaScript-Funktion

Was ich habe, ist so etwas wie dieses

Funktion doSomething() { ... }

... ***

ich kann manipuliere das *** (oben) aber ich kann die DoSomething Funktion nicht ändern ... Stattdessen muss ich irgendwie ein paar Codezeilen in das Ende des DoSomething Codes einfügen.

Der Grund, warum ich dies tun muss, ist, dass das benutzerdefinierte Framework doSomething() aufruft und dies zu einer ID führt, die vom Server zurückgegeben wird, den ich extrahieren muss. Diese ID wird nur innerhalb der doSomething-Funktion referenziert, so dass ich sie nicht abfangen kann, es sei denn, ich injiziere Code in diese Funktion (es sei denn, ich habe etwas verpasst).

Gibt es eine Möglichkeit, dies zu tun?

+3

Wie ist die Funktion 'gesperrt'? – Lazarus

+0

Mögliches Duplikat von [Gibt es eine Möglichkeit, alle JavaScript-Methoden mit einer Funktion zu versehen?] (Http://stackoverflow.com/questions/3919134/is-there-a-way-to-wrap-all-javascript-methods- with-a-function) –

Antwort

0

Funktionen sind erste Klassenwerte in Javascript, was bedeutet, dass Sie sie in Variablen speichern können (und tatsächlich deklariert eine benannte Funktion im Wesentlichen eine anonyme Funktion zu einer Variablen).

sollten Sie in der Lage sein, so etwas zu tun:

function doSomething() { ... } 

var oldVersionOfFunc = doSomething; 
doSomething = function() { 

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

    // your added code here 

    return retVal; 
} 

(Aber ich könnte falsch sein Mein Javascript ist ein wenig rostig,..))

+1

Wenn ich die Frage richtig gestellt habe, hilft das hier nicht, da das Problem darin besteht, den Wert einer lokalen Variablen zu extrahieren, auf die nur in 'doSomething' verwiesen wird. Und die neue Version von 'doSomething' kann nicht auf Variablen innerhalb des alten verweisen. –

5

es Alias.

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

Er benötigt Zugriff auf eine Variable, die auf die ursprüngliche Funktion beschränkt ist. – Matt

0

Ich kann nicht die Funktion doSomething ändern ... Statt

ein paar Zeilen in das Ende ein paar Zeilen Code in das Ende des doSomething-Code einzuspeisen Injizieren Ich muss irgendwie der doSomething Code klingt wie Ändern der doSomething Funktion, für mich. Ich denke leider, dass du geschraubt bist.

(Ich bin ein wenig verschwommen auf das alles, aber ich denke Funktionen sind wie Menschen, die über solche Dinge kümmern Informationen implementieren in JavaScript versteckt, gerade weil Sie nicht ihren Umfang von außen auf sie zugreifen können.)

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

Dies scheint ein Fehler (zu viel Rekursion)

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

Dies funktioniert für mich zu provozieren, auch wenn es hässlich ist.

2

Ich bin mir nicht sicher, was Sie mit "gesperrt" meinen - JavaScript wird von Ihrem Browser interpretiert. Selbst wenn es verkleinert oder codiert wurde, können Sie die Quelle dieser Funktion immer noch aus der Quelle der Skriptseite kopieren. An diesem Punkt weisen Sie die ursprüngliche Funktion einem eigenen Entwurf zu, der den kopierten Code plus Ihren eigenen enthält.

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

Vielen Dank für Ihr Feedback. Jede Antwort gab mir einen Hinweis und als solche habe ich die folgende Lösung gefunden.

<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

Eine bessere Lösung (erfordert keine DOM-Manipulation, ist reines Javascript): http://StackOverflow.com/a/9134757/39722 –

1

die Funktion zu verändern, indem sie mit den Source-Code-Strings arbeiten kann ganz einfach sein. Um es für eine bestimmte Instanz zu tun, versuchen:

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

Jetzt doSomething die ID zurückgibt. Ich bin normalerweise kein Fan von eval, aber normale aspect oriented programming Techniken gelten hier nicht, aufgrund der Voraussetzung für den Zugriff auf eine lokale Variable.

Wenn doSomething bereits einen Wert zurückgibt, versuchen:

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

diese in eine Funktion zu aktivieren, müssen wir den Code machen in globalen Bereich zu bewerten:

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

Wenn Sie neu schreiben wollen Methoden und anonyme Funktionen an Variablen gebunden, ändern insertCodeBefore an:

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

Beachten Sie, dass das erste Argument für die Funktionen jetzt Strings sind. Wir können andere Funktionen definieren:

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

Dies wird nicht funktionieren im allgemeinen Fall, weil die Funktion zu einem früheren Zeitpunkt eine Rückgabe ausführen kann, so dass der injizierte Code möglicherweise nicht erreicht wird. –

Verwandte Themen