[英]How to dynamically change the contents of a function using JavaScript
為了幫助理解此功能,該功能在html頁面中並且已生成,因此我無法更改生成的代碼:
function Update_qu7260() {
var newVal = ''
for( var idx = 0; idx < 2; idx++ )
{
var test
if( idx == 0 ) test = text7263
else if( idx == 1 ) test = text7265
if( test.matchObj ) newVal += test.leftSel + "-" + test.matchObj.rightSel + ","
}
newVal = newVal.substring( 0, newVal.length-1 )
VarQuestion_0001.set( newVal )
qu7260.hasBeenProcessed=false;
doImmFeedback('qu7260');
}
var qu7260 = new Object();
...
qu7260.updFunc = Update_qu7260;
var qObj=[qu7260];
請注意,在上面的數字“ 7260”中,數字從1開始,所以它們很多,並且每個Update_###()
都不同,因此我無法用“硬接線”代碼重寫它們。 我的代碼在外部JavaScript文件中,並在onLoad上執行:
...
var updFunc = qObj[0].updFunc.toString();
if(updFunc.indexOf('doImmFeedback(')!=-1){
updFunc = updFunc.replace('doImmFeedback','doImmQuestionFeedback'); // do my function
updFunc = updFunc.replace('function ',''); // remove the word function
var funcName = updFunc.substr(0,updFunc.indexOf('(')); // get the function name e.g. Update_qu7260
updFunc = "window['" + funcName + "']=function" + updFunc.replace(funcName,'');
eval(updFunc);
}
...
當我將eval()更改為alert()時,我可以看到它是正確的,但是,eval()沒有引發任何錯誤,並且未調用我的函數doImmQuestionFeedback
。 當我隨后執行alert(qObj[0].updFunc.toString())
我看到了原始功能。
看來我提供的信息太復雜了,因此以下代碼是一個更好的示例:
function hi(){alert('hi');}
function changeHi(){
hi(); // I get an alert box with hi
newHi = "function hi(){alert('hi there');}"
eval(newHi);
hi(); // I get an alert box with hi
window.setTimeout('hi()',500); // I get an alert box with hi
}
window.setTimeout('changeHi()',500);
以下是原始問題:
我有一個未創建的預定義函數,但是,我知道它的名稱,因此我可以獲取該函數本身,然后通過執行以下操作對其進行更改:
var funcText = window.updateFunc.toString();
funcText = funcText.replace('doSomeOtherFunction(','doMyFunction(');
我如何更新實際函數,以便它將執行以前做過的所有事情,除了現在將調用doMyFuntion()?
下面是一個示例,可以幫助您直觀地了解我想做什么,我需要更改的實際功能非常復雜。 我有:
function updateFunc(whatToUpdate,true){
... - do lots of stuff.
var retVal = doSomeOtherFunction(whatToUdate);
... - do lots of stuff based on retVal
}
我需要將其更改為:
function updateFunc(whatToUpdate,true){
... - do lots of stuff
var retVal = doMyFunction(whatToUdate);
... - do lots of stuff based on retVal, I have had a chance to change retVal
}
然后,我的函數要做的第一件事就是調用doSomeOtherFunction()來檢查/更改返回的值,然后將該值返回給updateFunc()。
我試圖操縱上面的funcText來:
funcText = 'window.updateFunc = function(...';
eval(funcText);
沒有成功。
這可能已經足夠關閉您想要的內容。
假設您具有此原始功能:
function originalFunc(val) {
// this function converts input string to upper case
return val.toUpperCase();
}
現在,您想在執行該函數之前或之后將其重寫為某些內容(在此示例中,我們在此函數之前或之后執行當然並不重要)。
// we preserve orignal function
var originalFunc_save = originalFunc;
// now we override the original function with this block
var originalFunc = function(text) {
// lets call the orignal function
text = originalFunc_save(text);
// now do our custom thing
return text.split('').reverse().join('');
}
因此,我們的測試應該可以工作。
var text = 'This is a test';
console.log(originalFunc(text));
輸出:
TSET A SI SIHT
如果必須重寫類中的函數,則此方法也適用。 我們唯一需要注意的是選擇一個不會干擾原始類代碼的已保存名稱。 _save可能不夠好,但是您明白了。
更新:我正在上面的代碼中更新,以使用指向原始函數的字符串變量。 我認為這就是OP想要的。
由某些庫定義的原始代碼
function originalFunc(val) {
// this function converts input string to upper case
return val.toUpperCase();
}
現在,我們使用func字符串變量指向該函數並執行它。
var text = 'This is a test';
var func = 'originalFunc';
text = window[func](text);
console.log(text);
輸出:當然,我們得到了最初的預期結果,因為我們沒有覆蓋它。
THIS IS A TEST
現在,我們使用指向函數的字符串編寫代碼以覆蓋原始函數行為。
// let's define a new function string
var funcSaved = func + '___saved';
// now preserve the original function code
window[funcSaved] = window[func];
// override the original function code block
window[func] = function(text) {
// lets call the orignal function
text = window[funcSaved](text);
// now do our custom thing
return text.split('').reverse().join('');
}
// let's test the code
text = 'This is a test';
text = window[func](text);
console.log(text);
輸出:
TSET A SI SIHT
我認為您這樣做的方式太復雜了。 如果僅在doMyFunction
和doSomeOtherFunction
之間進行切換,則可以僅在某處創建一個標志,告訴您在if
語句中使用一個或另一個。
如果要使用事先不知道的名稱調用函數,並且僅在運行時獲得名稱,則可以接受該函數作為參數調用,也可以接受該函數的名稱作為參數,然后像這樣調用它: var retVal = window[functionName]();
(假設functionName
是window
對象的屬性)。
我強烈建議直接接受函數作為參數,因為該函數可能未在全局范圍內定義。
編輯:在您澄清之后,我想,我可以給您滿意的答案:
如果您有一個字符串,如var functionString = "function updateFunc(whatToUpdate){var retVal = doMyFunction(whatToUpdate);}";
您可以使用Function
對象定義函數: window.updateFunc = new Function("whatToUpdate", "return (" + functionString + ")(whatToUpdate)");
這將替換已經存在的函數,並且只要您知道並指定參數,就可以為它提供任何想要的有效函數字符串。
如果我理解正確,則您想覆蓋外部功能。 您可以使用以下代碼來實現
//Someone else's function
function externalFunction(foo){
return "some text";
}
//Your function
function myFunction(value){
//Do something
}
//Override
var externalFunction = (function(){
var original = externalFunction; //Save original function
return function(){
var externalFunctionReturnValue = original.apply(this, arguments);
return myFunction(externalFunctionReturnValue);
}
})();
我強烈建議不要使用eval,但是由於您想從字符串中解析javascript:
function hi(){alert('hi');}
function changedHi(){
hi(); // I get an alert box with hi
newHi = "window['hi'] = function(){alert('hi there');}"
eval(newHi);
hi(); // I get an alert box with hi there
window.setTimeout('hi()',500); // I get an alert box with hi there
}
window.setTimeout('changedHi()',500);
更新:
此代碼段有效,它是您的原始代碼:
<script type="text/javascript">
function doImmFeedback(foo){
console.log("DoImmFeedback: " + foo);
}
function Update_qu7260() {
console.log("Some code")
doImmFeedback('qu7260');
}
</script>
<script type="text/javascript">
var qu7260 = new Object();
qu7260.updFunc = Update_qu7260;
var qObj=[qu7260];
var updFunc = qObj[0].updFunc.toString();
if(updFunc.indexOf('doImmFeedback(')!=-1){
updFunc = updFunc.replace('doImmFeedback','doImmQuestionFeedback'); // do my function
updFunc = updFunc.replace('function ',''); // remove the word function
var funcName = updFunc.substr(0,updFunc.indexOf('(')); // get the function name e.g. Update_qu7260
updFunc = "window['" + funcName + "']=function" + updFunc.replace(funcName,'');
console.log(updFunc);
eval(updFunc);
}
function doImmQuestionFeedback(foo){
//Your function
console.log("doImmQuestionFeedback: " + foo);
}
Update_qu7260(); //This executes your doImmQuestionFeedback
</script>
因此,如果您的函數未運行,則您的函數不在全局范圍內,或者正在發生其他情況,因此我們無法知道是否沒有更多信息。 檢查您的開發者控制台是否存在javascript錯誤。
我相信這是一個有效的用例被遺忘的JavaScript with
功能。
基本思路:你叫原updateFunc
提供自己的版本doSomeOtherFunction
使用它with
命名空間注入:
function updateFunc(whatToUpdate,true){
... - do lots of stuff.
var retVal = doSomeOtherFunction(whatToUdate);
... - do lots of stuff based on retVal
}
function patchUpdateFunc() {
var original_doSomeOtherFunction = window.doSomeOtherFunction;
var original_updateFunc = window.updateFunc;
function doMyFunction() {
// call original_doSomeOtherFunction() here,
// do your own stuff here.
};
window.updateFunc = function() {
with ({doSomeOtherFunction: doMyFunction}) {
return original_updateFunc.apply(this, arguments);
}
}
}
patchUpdateFunc();
您可以克隆updateFunc
函數,自行決定對其進行編輯,然后在隨后的工作中使用它。
function updateFunc(whatToUpdate, param){ // the initial function
...
var retVal = doSomeOtherFunction(whatToUpdate);
return retVal;
}
// formation of unnamed function as string
var newfunc = updateFunc.toString().replace('function updateFunc', 'function ').replace('doSomeOtherFunction(', 'doMyFunction(');
function doMyFunction(whatToUpdate){ // your new function, just for example
console.log(parseInt(whatToUpdate) * 10);
}
var newUpdateFunc;
// declaring new version of 'updateFunc' function
// which is stored in 'newUpdateFunc' variable
eval("newUpdateFunc = " + newfunc);
newUpdateFunc(3); // outputs '30'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.