[英]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.