如何动态更改JavaScript函数中的一行代码?

5
假设我有以下函数:
function alertMesg()
{
   alert("This ok function alerts message!");
}

现在在运行时,我想更改alertMesg函数的功能以执行其他操作。我的想法是像这样做。
var temp = window.alertMesg.toString.replace("ok","great")
temp = temp.replace('function alertMesg()',"");
window.alertMesg = new Function(temp);

基本上,问题在于我无法控制alertMesg函数中的源代码。我想改变这个函数,但实际上我不能改变它的源代码,因为它是由服务器端生成的。话虽如此,我需要让它表现出不同的行为。
PS:我忘了提到一个重要的部分:我必须保留大部分函数。我不能直接替换函数。我必须将函数的95%保持原样,并更改另外5%。
@Barlow Tucker, quixoto, pekka 谢谢你们的关注。
基本上,我认为代理的想法行不通,因为我不仅仅是添加功能,我还要改变代码的功能。例如,我希望函数的第三行有所不同。在我的真实示例中,我必须在函数的中间添加一行。

可能是[JavaScript:覆盖alert()]的重复问题(https://dev59.com/X3I-5IYBdhLWcg3wsKh4) - Pekka
1
那个重复的答案应该可以解决它(请参考“代理模式”的被接受的答案,将 window.alert() 替换为您的函数)。 - Pekka
代理可能允许我向此函数添加功能,但它不允许我删除功能。 - GC_
我听说如果有人在做这种事情,就会有其他人要杀一些小猫咪。 - mykhal
1
你为什么想添加/删除功能呢?更多的信息可能会有所帮助。 - Barlow Tucker
@Grae:代理模式将解决您所述的问题。如果您的问题实际上更加复杂(您想要更改其他函数的内部机制,而不仅仅是警报的输出),请说明。最好的答案可能会有所不同。 - Ben Zotto
2个回答

13

如果你必须替换一个函数的内容,这是可能的:

function alertMesg()
{
   alert ("This ok function alerts my message!");
}

alertMesg(); // alerts "This ok function alerts my message!"

// do whatever you want to the function here
var temp = alertMesg.toString();
temp = temp.replace('my', 'your');

// now replace the original function
alertMesg=new Function(temp.substring(temp.indexOf('{')+1,temp.lastIndexOf('}')));

alertMesg(); // alerts "This ok function alerts your message!"

这可能不是实现你所尝试的目标的最佳方式,但除非你提供更多细节,否则我无法建议其他方法。


一开始我还跟得上,但是 eval 那里就有点懵了。仅仅在 temp 上调用 eval 就能神奇地改变 alertMesg 的值吗?我在 IE 上尝试了你的代码,但是出现了 JavaScript 错误。 - GC_
现在,我在最后一个alertMesg()调用时遇到了一个期望对象错误。 - GC_
alertMesg = new Function(temp.substring(temp.indexOf('{')+1,temp.lastIndexOf('}'))); 这行代码怎么样? - Dumb Guy
谢谢你的帮助。问题确实非常棘手,希望这能让事情变得更容易一些。 - GC_
这是至少一个整洁的技巧。当然,前后的字符串化不是非常有效率,但我相信你已经知道了。你提到这可能不是最好的方法。你可以详细说明一下想要将新行附加到函数中的使用情况吗?目前,我允许用户注册一个初始化脚本以替换 AJAX 调用期间重新绑定事件等内容。使用一个函数对象数组,AJAX 代码循环遍历该数组,将替换的元素传递给 init 函数。 - That Realty Programmer Guy
显示剩余3条评论

4
动态代码替换可能在某些情况下有效,但这是一条危险的道路 - 脆弱的,一步错就完了,并且很快就会变成维护的噩梦。正如一位评论者所说,更好的方法是仅包装本地的window.alert,然后在你关心的字符串出现时执行正确的操作,参见此答案:JavaScript:覆盖alert() (插入标准评论,建议让你的服务器端人员与你在同一个页面/团队上,这样你就不需要在自己的页面上进行hack了。)
更新:你不是在问alert,而是在普遍地问这个问题。是的,你可以像其他人建议的那样去做。但是如果你有函数的原始代码,为什么不直接替换它呢?如果你想要的函数是一个名为foo()的全局函数,你可以运行JS来实现:
window.foo = function() {
    // The stuff I know is there (A)
    ...
    // Some new stuff I want to change (B)
    ...
    // More stuff I know is there (C)
}

这将丢弃原始内容并用您的版本替换。虽然“猴子补丁”页面中的内容可以很好地工作,但一定会带来一些维护上的麻烦。

我在这里一定要注意,如果由于某种原因无法实现此操作,因此坚持在现有函数“文本代码替换”的中间进行操作,则滥用语言/环境以实现可维护性,并且在多个方面都会遇到困难。


假设原始函数有部分a、部分b和部分c。我希望新函数具有部分a、部分b、一个新部分,然后是部分c。使用覆盖,我只能让新函数像新部分、部分a、部分b、部分c,或者像部分a、部分b、部分c,然后是新部分。除非我理解有误,否则我添加的新部分不能在函数的中间,这是您的想法。 - GC_
我需要在函数的中间添加一些代码,而不是在开头或结尾。不过还是谢谢你的尝试。 - GC_
我需要修改的JavaScript函数是由JSF在服务器端动态生成的,每个页面都不同。我真的需要一个解决方案来让我修改现有的函数,因为我事先不知道函数中会有什么内容。它基本上遵循一种模式,我知道每次需要更改什么,但我不知道要更改的区域之前的所有内容。如果有帮助的话,我认为我可以猜测那个点之后的所有内容。 - GC_

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接