指定内联事件处理程序是否会调用eval()?

时间:2012-09-16 21:01:26

标签: javascript

如Douglas Crockford的 JavaScript,The Good Parts 所述,将字符串传递给setTimeoutsetInterval会调用eval(),应该避免:< / p>

setTimeout('console.log("this uses eval()");', 100);

考虑到这一点,使用内联事件处理程序时会发生同样的事情吗?:

<button onclick="console.log('click!');">Click Me</button>

换句话说,使用内联事件处理程序会在触发事件时产生额外的解析开销,或者在初始文档加载期间使用其他所有内容(例如内联脚本块,标题中的脚本等)完成解析。

1 个答案:

答案 0 :(得分:4)

是的,比喻说,确实如此。 页面中的所有 javascript的解析方式与传递给eval()的代码完全相同。要避免eval(),主要是因为它比普通代码慢,因为它需要额外的解析。

您可以验证浏览器是否已编译处理程序或重新编译它,至少对于具有不错开发人员工具的浏览器(示例代码使用jQuery,但当然您可以在普通JS中重写它):

<div id="test" onclick="alert('tested')">Click</div>
<script>
console.log(typeof $('#test')[0].onclick);
console.log($('#test')[0].onclick);
</script>

在我的Chrome测试中,会记录以下内容:

Type of handler: function
function onclick(event) {
  alert('click')
} 

很明显,onclick属性是编译的function值。您还可以看到处理程序的额外生成代码,即围绕内联代码的函数。您还可以在处理程序中设置断点并观察堆栈跟踪,以验证其中的任何位置都没有eval调用。