2010-01-21 93 views
7

我有一個奇怪的問題,因爲我需要將一些javascript注入另一個javascript函數。我正在使用一個鎖定的框架,所以我無法更改現有的功能。將JavaScript注入javascript函數

我有什麼是這樣的

功能DoSomething的(){ ... }

... ***

我可以操縱***(上面)但是我不能改變doSomething函數......相反,我需要以某種方式在doSomething代碼的末尾註入幾行代碼。

我需要這樣做的原因是自定義框架調用doSomething(),這導致從我需要提取的服務器返回一個ID。這個ID只在doSomething函數內部引用,所以我不能捕捉它,除非我注入代碼到該函數(除非我錯過了某些東西)。

有沒有辦法做到這一點?

+3

功能是如何「鎖定」的? – Lazarus 2010-01-21 12:22:53

+0

[有沒有辦法用函數包裝所有JavaScript方法?](http://stackoverflow.com/questions/3919134/is-there-a-way-to-wrap-all-javascript-methods-函數) – 2016-07-14 04:47:34

回答

0

函數是Javascript中的第一類值,這意味着您可以將它們存儲在變量中(實際上,聲明一個命名函數本質上是將一個匿名函數賦值給一個變量)。

你應該能夠做這樣的事情:

function doSomething() { ... } 

var oldVersionOfFunc = doSomething; 
doSomething = function() { 

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

    // your added code here 

    return retVal; 
} 

(不過,我可能是錯的我的JavaScript是一個有點生疏;))

+1

如果我的問題是正確的,那麼這裏就不會有幫助,因爲問題是提取只在'doSomething'內引用的局部變量的值。而新版本的'doSomething'不能在舊版本中引用變量。 – 2010-01-21 12:08:48

5

別名它。

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

他需要訪問範圍限定於原有的功能 – Matt 2010-01-21 14:54:06

0

我不能改變DoSomething的功能......相反,我需要以某種方式注入的幾行代碼到DoSomething的代碼

注入幾行到月底結束代碼的doSomething聽起來像改變doSomething函數,對我來說。不幸的是,我認爲你被搞砸了。

(我在這一切都有點朦朧,但我認爲功能是人誰擔心這樣的事情是如何實現信息隱藏在JavaScript中,正是因爲你不能訪問它們以外的範圍。)

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

這似乎激怒了錯誤(太多遞歸)

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

這個工作對我來說,即使它是醜陋的。

2

我不確定您的意思是「鎖定」 - JavaScript是由您的瀏覽器解釋。即使它已被縮小或編碼,仍然可以從腳本頁面的源中複製該函數的源。此時,您將原始功能重新分配給您自己的設計之一,其中包含複製的代碼和您自己的設計。

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

感謝您的反饋。每個答案給了我一個線索,因此我提出了以下解決方案。

<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

更好的解決方案的變量(不需要DOM操作,是純JavaScript):http://stackoverflow.com/a/9134757/39722 – 2015-09-27 07:07:30

1

通過與源代碼串的工作改變功能可以說是相當簡單的。要爲特定實例執行此操作,請嘗試:

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

現在doSomething返回ID。我通常不是eval的粉絲,但由於需要訪問本地變量,因此在這裏不適用aspect oriented programming技術。

如果doSomething已經返回一個值,嘗試:

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

把它變成一個功能,我們需要在全球範圍內的代碼評估:

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

如果你想重寫方法和匿名函數綁定到變量,將insertCodeBefore更改爲:

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

注意函數的第一個參數現在是字符串。我們可以定義其他功能:

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

這將無法正常工作在一般情況下,因爲該函數可以在任何時間更早執行返回,因此可能無法達到注入的代碼。 – 2014-08-29 07:47:26