2010-01-21 11 views
7

Mam dziwne pytanie, że muszę wstrzyknąć trochę javascript do innej funkcji javascript. Używam ramek, które są zablokowane, więc nie mogę zmienić istniejącej funkcji.Wstrzykuję javascript do funkcji javascript

Co mam coś takiego

funkcja doSomething() { ... }

... ***

mogę manipulować *** (powyżej) jednak nie mogę zmienić funkcji Zrób coś ... Zamiast tego muszę jakoś wprowadzić kilka linii kodu na końcu kodu DoSomething.

Powodem, dla którego muszę to zrobić, jest to, że niestandardowe wywołania framework doSomething() powodują zwrócenie identyfikatora z serwera, który muszę wyodrębnić. Ten identyfikator występuje tylko wewnątrz funkcji DoSomething, więc nie mogę go złapać, dopóki nie wprowadzę kodu do tej funkcji (chyba że coś przeoczyłem).

Czy istnieje sposób, aby to zrobić?

+3

Jaka jest funkcja "zablokowana"? – Lazarus

+0

Możliwy duplikat [Czy istnieje sposób na zawijanie wszystkich metod JavaScript za pomocą funkcji?] (Http://stackoverflow.com/questions/3919134/is-there-a-way-to-wrap-all-javascript-methods- with-a-function) –

Odpowiedz

0

Funkcje są pierwszymi wartościami klas w Javascript, co oznacza, że ​​można je przechowywać w zmiennych (w rzeczywistości deklarowanie nazwanej funkcji zasadniczo przypisuje anonimową funkcję do zmiennej).

Powinieneś być w stanie zrobić coś takiego:

function doSomething() { ... } 

var oldVersionOfFunc = doSomething; 
doSomething = function() { 

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

    // your added code here 

    return retVal; 
} 

(Ale mogę się mylić Moje javascript trochę zardzewiały;..))

+1

Jeśli mam pytanie w porządku, nie pomoże to tutaj, ponieważ problem polega na wyodrębnieniu wartości zmiennej lokalnej, do której odwołuje się tylko wewnątrz 'doSomething'. A nowa wersja 'doSomething' nie może odwoływać się do zmiennych w starym. –

5

Alias ​​to.

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

potrzebuje dostępu do zmiennej, która ma zasięg do pierwotnej funkcji – Matt

0

nie mogę zmienić funkcję doSomething ... Zamiast muszę jakoś wstrzyknąć kilka linijek kodu na końcu kodu doSomething

wstrzykując kilka linii do końca kodu doSomething brzmi jak zmiana funkcji doSomething dla mnie. Myślę, niestety, że jesteś spieprzony.

(jestem nieco zamglony na to wszystko, ale myślę, że funkcje są jak ludzie, którzy martwią się o takich rzeczach wdrożyć ukrywanie informacji w JavaScript, właśnie dlatego, że nie może uzyskać dostępu do ich zakresu spoza nich).

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

wydaje się sprowokować błąd (zbyt dużo rekursji)

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

działa to dla mnie, nawet jeśli jest brzydka.

2

Nie jestem pewien, co masz na myśli przez "zablokowany" - JavaScript jest interpretowany przez twoją przeglądarkę. Nawet jeśli został minified lub zakodowany, nadal możesz skopiować źródło tej funkcji ze źródła strony skryptu. W tym momencie ponownie przypisujesz oryginalną funkcję do jednego z własnych projektów, który zawiera skopiowany kod oraz własny.

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

Dzięki za wszystkie opinie. Każda odpowiedź dała mi wskazówkę i jako taki wymyśliłem następujące rozwiązanie.

<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

Lepsze rozwiązanie (nie wymaga manipulacji DOM, jest czystym Javascriptem): http://stackoverflow.com/a/9134757/39722 –

1

Zmiana funkcji poprzez współpracę z ciągów kod źródłowy może być całkiem proste. Aby zrobić to w konkretnym przypadku, spróbuj:

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

Teraz doSomething zwraca identyfikator. Zwykle nie jestem fanem eval, ale normalne techniki aspect oriented programming nie mają tu zastosowania ze względu na wymaganie dostępu do zmiennej lokalnej.

Jeśli doSomething już zwraca wartość, spróbuj:

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

Aby przekształcić funkcję, musimy uczynić kod oceny w zakresie globalnym:

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

Jeśli chcesz przerobić metody i anonimowe funkcje powiązane ze zmiennymi, zmień insertCodeBefore na:

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

Zwróć uwagę, że pierwszym argumentem funkcji są teraz ciągi. Możemy zdefiniować inne funkcje:

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

To nie zadziała w ogólnym przypadku, ponieważ funkcja może wykonać zwrot w dowolnym momencie wcześniej, więc może nie dotrzeć do wstrzykniętego kodu. –