javascript - 如何使用 JavaScript 动态更改函数的内容

标签 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 文件中并在加载时执行:

...
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

关于javascript - 如何使用 JavaScript 动态更改函数的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34831261/

相关文章:

javascript - Struts2上传多个文件前如何显示选中的文件名?

javascript - 无法在 find() 中设置和获取变量值

javascript - webpack2可以像SystemJS一样动态加载模块吗

javascript - Jquery ajaxForm 表单提交后清除表单

javascript - Bootstrap 导航栏下拉菜单的问题

javascript - IE8 不呈现正确的响应内容

javascript - 如何在 IE7、8 上使用 javascript 获取图像宽度、高度和文件类型,选择文件后?

javascript - IE8 错误与具有 jQuery 函数的 javascript 文件?

javascript - 在 jquery/javascript 中单击时将元素移动到轮播的中间

javascript - 无法在 StatusCode 回调中设置值