探讨FantasySoft遇到的有关Javascript的疑问
看到了FantasySoft遇到的疑问,这里只探讨第一个疑问:
跟FantasySoft 一样,以前确实没有碰到过这种情况。:)从这个问题来看,一直注意采用尽可能不引起错误的规则(比如此处的命名)是重要的。
原文部分:
<head>
<script language="javascript">
function order()
{
alert();
}
</script>
</head>
<body>
<form>
<input type="button" name="order" value="Click Me" onclick="order()" />
</form>
</body>
</html>
代码很简单,如果按了"Click Me"按钮后,是否会如愿弹出一个对话框呢?事实上,是不会的。原因是button的name与Javascript方法名字相同了,结果就造成了order方法没有被调用。解决办法是只要将方法名字做修改即可。虽然我知道了错误的原因,但是我却不知道为什么会这样,毕竟两者的作用域是不同的啊。
由于水平有限,仅仅想到以下这些(当然语义范围为Javascript),错误之处请大家包涵和指正:
1 从数据类型的角度来讲,Function属于对象,为引用类型。函数名(它是一个变量)引用Function对象。这里的function order(){alert();}为:order引用或者说代表“function() {alert();}”。看以下变形代码:
<input type="button" name="order" value="Click Me" />
<script language="javascript">
window.document.all["order"].onclick=function(){alert();};
</script>
</form>
2 从另一个角度来看:Javascript的‘顶层’对象为全局对象global Object,当定义一个全局变量global variable时,它实质上是定义全局对象的一个属性property。(Javascript解释器开始运行且在执行任何Javascript代码之前时首先初始化创建global Object,其属性(也就是定义的全局变量)引用预定义值或函数。对应地,局部变量local variable是call Object的属性。)
<script language="javascript">
function order(){alert();}
</script>
实际上是:
<script language="javascript">
var order=function(){alert();}
</script>
变量order为global Object的一个属性,它引用了自定义的函数。
3 作为Client-side Javascript,它是指在网页浏览器的客户端环境下的Javascript编程。此时,Window对象作为全局对象global Object和全局运行上下文。input元素的name属性值"order" 代表input元素,即window.document.all["order"],这时,函数function order(){alert("123");}的函数名order和代表input元素的order都是全局运行上下文中的变量。而代表input元素的order显然是一个form对象(更准确的说是在input元素对应的Button对象)作用范围内的局部变量,在此作用范围内它覆盖了其上定义的引用函数function(){alert("123");}的全局变量order。所以,当input元素的onclick属性触发事件时,它调用处理函数,而处理函数由名为order的变量所引用,所以它查找名为order的变量。而Javascript中变量的作用链是如下图这样的:
所以它首先查找到了与onclick属性相同作用范围的局部变量即代表input元素的order,而不是找到了真正引用处理函数的全局变量order。而代表input元素的order由于没有引用的有处理函数,所以Javascript解释器运行时提示有错误(窗口左下角状态栏的黄色感叹号)。而修改两个order之一的命名则运行成功。
可以考虑以下变形的代码:
function order(){alert();}
var or=order;
</script>
<form>
<input type="button" name="order" value="Click Me" onclick="or()" />
</form>
[修正]
我重新审视的时候才发现现在我用黄色标注的部分是有问题的!大家仔细看看代表input元素的order是全局运行上下文中的变量这句,我竟然昏头昏脑的把input元素的Attibute之一name(即Javascript上下文环境下的form对象下的属性)的值"order"作为一个变量来了!( 不知道当时是怎么想的了?! )从而后面的解释也就是错误的了......那究竟是什么原因造成所探讨的疑问的呢?,但是这个问题也可以不做深究,因为对于实际的编程技能没有什么影响,只要知道即可。:)我的想法是很可能Client-side Javascript的语义根本就不允许HTML元素的name或id值与相关的函数名相同(为了避免Javascript解释时可能出现错误),从而当Javascript解释器运行时检查到这种问题便提示有错误,运行不通过.