我有一个无法运行并抛出错误的 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
最佳答案
要为此处发生的事情添加一些细节,您需要了解 javascript 的作用域链。
作用域对象
作用域对象是在执行函数时创建的隐藏对象,在其上使用 var
声明的变量被放置为属性,执行函数中的任何命名的 function
也是也作为属性放置在范围对象上。
当请求诸如 mytest
的标识符时,javascript 会搜索附加到当前范围对象的名称(顺便说一下,范围对象也称为“执行上下文”)。
范围链
当在函数内部声明函数时,当前作用域对象附加到该函数。当这个内部函数正在执行时(因此有自己的作用域对象),执行的代码不仅可以访问当前作用域对象,还可以访问创建当前正在执行的函数的作用域对象。 停在这里,重新阅读最后一句话。这就是众所周知的作用域链,链的深度与函数内部的函数一样深(这种情况经常发生当使用像 JQuery 这样的框架时)。
因此,当在当前作用域对象上搜索标识符失败时,它会查看链上的下一个作用域对象。它一直沿着链向上走,直到它到达全局对象(在全局级别声明的函数将全局对象作为它们的范围对象)。
事件属性异常
当浏览器在诸如 onclick 之类的属性文本中执行代码时,它会将此代码视为一个函数。但是,浏览器会使用附加到此“功能”的明显作用域链来做一些奇怪的事情。通常,它们将当前元素和文档元素(可能还有介于两者之间的其他元素)作为作用域对象注入(inject)到作用域链中。
例如,将示例中的 onclick 代码更改为“alert(href)”。您将在警告框中看到页面路径后跟 #
。这是因为当前元素在范围链中,因此 href
由其 href
属性解析。
在问题的情况下,代码到达范围链中的 document
(位于全局窗口对象之上)并找到标识符“mytest”(这是对表单的引用) 并因此尝试将其值用作函数(但失败了)。
关于Javascript 函数和表单名称冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1415747/