我有一个不会运行的javascript函数并抛出错误。花了大约一个小时才意识到我的表单与函数名称相同。表单名称与函数名称冲突似乎很奇怪,但我仍然更改名称,一切正常。有谁知道为什么会发生这种情况?
如果您运行此代码,它将失败,但如果您更改表单名称,则会非常奇怪。
<html>
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<script type="text/javascript">
function mytest(){alert("hello");}
</script>
</head>
<body>
<form name="mytest" ></form>
<a href="#" onClick="mytest();">Click Me</a>
</body>
</html>
我在IE6上运行它。对我来说奇怪的是,一个是Javascript代码,另一个是HTML的属性。
直播链接,您可以看到这种情况发生:
JSBin
答案 0 :(得分:7)
要在这里添加一些细节,你需要了解javascript的范围链。
范围对象
作用域对象是在执行函数时创建的隐藏对象,其中使用var
声明的变量作为属性放置,执行函数内的任何已命名的function
也作为属性放置在范围对象。
当请求mytest
之类的标识符时,javascript会搜索附加到当前范围对象的名称(顺便说一下,范围对象也称为“执行上下文”)。
范围链
在函数内声明函数时,当前作用域对象附加到函数。当此内部函数正在执行时(因此具有自己的作用域对象),执行的代码不仅可以访问当前作用域对象,还可以访问创建当前正在执行的函数的作用域对象。 停在这里,重新阅读最后一句。这就是所谓的范围链,链条将与函数内部的函数一样深(这种情况发生了很多当使用像JQuery这样的框架时。
因此,当在当前范围对象上搜索标识符失败时,它会查看链上的下一个范围对象。它一直向上走,直到它到达全局对象(在全局级别声明的函数将全局对象作为其范围对象)。
事件属性怪异
当浏览器在诸如onclick之类的属性文本中执行代码时,它会将此代码视为一个函数。但是,浏览器会使用附加到此“功能”的明显范围链来执行奇怪的操作。通常,它们将当前元素和文档元素(以及可能的其他元素)注入到作用域链中,就好像它们是作用域对象一样。
例如,将示例中的onclick代码更改为“alert(href)”。您将在警告框中看到页面的路径,后跟#
。这是因为当前元素位于作用域链中,因此href
属性解析href
。
在问题的情况下,代码到达范围链中的document
(放置在全局窗口对象上方)并找到标识符“mytest”(它是对表单的引用),因此尝试将其值作为函数使用(并失败)。
答案 1 :(得分:6)
该函数是window
对象中的成员,该表单是forms
对象中document
集合的成员。当脚本查找标识符“mytest”的匹配项时,它首先查找document
对象,如果找不到它,则会查找window
对象。
如果您指定它位于window
对象中,即使使用冲突的表单名称,也可以访问该函数:
<a href="#" onClick="window.mytest();">Click Me</a>