在JavaScript中使用“eval”时处理“return false”

在JavaScript中使用“eval”时处理“return false”,javascript,eval,Javascript,Eval,我要处理的情况是,我需要将jQuery事件绑定到一个页面,以处理通过JSF生成的UI更新。唉,JSF糟透了,它会在所有东西上粘贴onclick事件,这会抢占我的任何jQuery工作 多亏了这里的好朋友,我找到了一个解决方案: 逻辑是: 在页面加载时,抓住所有onclick属性并将它们存储在变量中 绑定我的jQuery事件 在我自己的jQuery事件之后,我可以eval原始onclick:eval(onclickValueVariable) 这在我所有的虚拟onclick事件测试中都有效 但

我要处理的情况是,我需要将jQuery事件绑定到一个页面,以处理通过JSF生成的UI更新。唉,JSF糟透了,它会在所有东西上粘贴onclick事件,这会抢占我的任何jQuery工作

多亏了这里的好朋友,我找到了一个解决方案:

逻辑是:

  • 在页面加载时,抓住所有
    onclick
    属性并将它们存储在变量中
  • 绑定我的jQuery事件
  • 在我自己的jQuery事件之后,我可以
    eval
    原始onclick:
    eval(onclickValueVariable)
这在我所有的虚拟onclick事件测试中都有效

但是,它在那个实时JSF页面上失败了。问题是所有onclick的结尾都带有一个“return false”,这会导致此错误:

return not in function
例如:

<div class="uglyJSFcreatedTag" onclick="console.log('hey');return false">
问题是
返回false
。发射eval时看起来什么都不能返回

有解决办法吗?我想象我可以将该值作为一个字符串,进行字符串解析以删除所有返回false,然后从脚本本身调用它。但这听起来有点混乱。有更优雅的解决方案吗


如果没有,在调用
eval
之前,我应该寻找哪些特定的JS语句来过滤掉?

我认为将代码包装在匿名函数中并立即调用应该比过滤掉返回语句更容易

evalCode = "function() {" + evalCode + "}()";
两种选择:

1。使用当前方法,在求值onclick字符串之前,只需使用函数包装它。存储结果,并将其作为函数调用。确保使用适当的
上下文调用它:

var f = eval("(function(){ "+cacheOnclick+"})");
f.call($jsfTag[0]);
注意:函数声明周围的括号
()
,在eval中是必需的。这使得声明成为一个表达式(从语法上讲),从而使其在eval中合法

2.从dom元素本身获取实际函数,而不是获取onclick属性。此外,除非您需要从代码中对jsf处理程序函数进行特殊处理,否则我建议您直接将jsf函数添加为jquery click处理程序,而不是从代码中显式调用它:

var $jsfTag = $('.uglyJSFcreatedTag');
$jsfTag.bind('click', $jsfTag[0].onclick);
$jsfTag.removeAttr('onclick');
就我个人而言,我会选择方法2,但其中任何一种都应该有效


更新:下面是对选项2的一点补充说明:

这来自您的示例——我们使用jquery检索一个集合,该集合包含类名为“uglyJSFcreatedTag”的所有元素

$jsfTag.bind('click', $jsfTag[0].onclick);
这将从集合中获取第一个元素(
$jsfTag[0]
),并获取该元素对象的
onclick
属性
.onclick
是一个javascript属性,它包含对浏览器根据“onclick”属性的字符串内容生成的编译函数的引用。现在,由于我们有了handler函数,我们可以使用jquery将它直接绑定到jquery单击事件

最后,我们只需删除该属性。这没关系,因为我们已经通过jquery绑定了函数。如果我们不从“旧式”onclick中删除它,那么它将被调用两次

注意:您可能已经注意到,上述代码仅适用于所选集合中的第一个元素。对于集合包含多个元素的非常可能的情况,您需要在集合中循环并分别处理每个元素。以下是您将如何做到这一点:

var $jsfTag = $('.uglyJSFcreatedTag');
$jsfTag.each( function(idx, element) {
    $(element).bind('click', element.onclick).removeAttr("onclick");
});
如果您想跳过某些元素的jsf处理程序,那么在“每个循环”中插入逻辑来测试它,并相应地跳过绑定调用



如果您必须继续从单击处理程序中调用JSF处理程序,那么至少考虑使用<代码>元素。OnCutter < /C> >而不是<代码> $(元素)。后者需要eval,而前者不需要。

老实说,我不知道你想做什么,但我想我能帮上忙。你为什么不以同样的方式添加所有听众?i、 要么全部使用JSF,要么全部使用jQuery。我不是在写JSF。我看不出通过向后的JSF方式添加更多的UI逻辑是朝着正确方向迈出的一步。我的工作是根据JSF团队给我的,让UI尽可能地工作。它让人想起了SharePoint工作的日子……在黑客之上的黑客。;)关闭,但是当调用(以前的)内联处理程序时,它的this关键字不会引用元素,因此还有一个问题需要处理。第一个问题对我来说似乎很有意义。但是,这会产生一个不同的错误:
函数语句需要一个名称
。我不确定第二种选择是否对我们有效,尽管我不得不承认我没有完全遵循第二种选择的做法。我应该提到的是,我们并不总是希望onclick进行求值(我们有一些逻辑来决定它是否触发)。#2是首选,#1是非常难看的。如果在函数周围包含括号,就不应该出现这种错误。在我发表第一篇文章后,我立即在编辑中添加了这些内容(以及相应的注释),所以你可能错过了它们。也就是说,#2确实是一种更干净的方法,它不涉及使用
eval()
(除非您真的需要,否则通常应该尽量避免使用)。啊!我想我现在有了第二个选择。这是否正确:第2行=通过jQuery绑定一个新事件(恰好是onclick属性)。第3行=删除onclick事件属性。因此,在这种情况下,如果我想绑定我自己的东西并在原始onclick之前激活,我只需要在第2行之前绑定,对吗?#2的唯一问题是我并不总是希望onclick激活……如果它已经绑定,那么可能会使if/else逻辑更混乱。。。
$jsfTag.bind('click', $jsfTag[0].onclick);
$jsfTag.removeAttr('onclick');
var $jsfTag = $('.uglyJSFcreatedTag');
$jsfTag.each( function(idx, element) {
    $(element).bind('click', element.onclick).removeAttr("onclick");
});