为了账号安全,请及时绑定邮箱和手机立即绑定

为什么JS函数名与元素ID冲突?

为什么JS函数名与元素ID冲突?

肥皂起泡泡 2019-06-29 10:23:45
为什么JS函数名与元素ID冲突?我有两个几乎相同的简单JS摆弄,在选择变更时调用一个函数。在这两种情况下,函数名都与SELECT ID相同,但由于某种原因,第一个命令工作得很好,而第二个函数由于JavaScript错误而失败。is not a function:http://jsfiddle.net/AZkfy/7/-在FF9(Linux)、Chromium16(Linux)、IE8(Windows)中工作良好:<script>     function border(border) { alert(border); }</script><select id='border' name='border' onchange='border(this.value)'>     <option value='foo'>foo</option>     <option value='bar'>bar</option></select>和http://jsfiddle.net/cYVzk/-FF9(Linux)、Chromium16(Linux)、IE8(Windows)失败:<script>     function border(border) { alert(border); }</script><form><select id='border' name='border' onchange='border(this.value)'>     <option value='foo'>foo</option>     <option value='bar'>bar</option></select></form>第一我不明白为什么第一个成功,第二个失败。第二-对于相互冲突的JS函数名和元素ID是否有任何JS规范或限制?
查看完整描述

3 回答

?
一只斗牛犬

TA贡献1784条经验 获得超2个赞

这是一个遗留的范围链问题,起源于JavaScript1.0到1.3,当时编程语言与我们现在所称的DOMAPI(当时的“动态HTML”)没有区别。

如果窗体控件(此处:select元素)是窗体的一部分(form元素),则Form对象,该对象表示form元素是控件事件处理程序属性值范围链中的第三个-下一个(第二个-下一个是表单控件对象本身,其次是该代码的变量对象)。

JavaScriptJava是由BrendanEich(当时在Netscape)设计的,它是一种编程语言,对于初学者来说很容易使用,并且可以很好地处理™文档(作为对Sun的JAVA的补充;因此它是一个永远令人困惑的名字)。因为在早期语言和(Netscape)DOM API是一种,这种简化(过度)也适用于DOMAPI:Form对象具有包含在其表示为引用相应窗体控件对象的属性名称的窗体中的控件的名称。..你可以写

myForm.border

它是符合标准的专有速记(W3C DOM级别2 HTML),但同样向后兼容

document.forms["myForm"].elements["border"]

现在,如果在窗体控件的事件处理程序属性值中使用窗体控件的名称以某种形式,就像

<form …>
  <… name="border" onchange='border(this.value)' …></form>

这和你写的一半专利一样

<form …>
  <… name="border" onchange='this.form.border(this.value)' …></form>

或者是符合标准的

<form …>
  <… name="border" onchange='this.form.elements["border"](this.value)' …></form>

因为一个潜在的全球border()函数的属性。ECMAScript最后一个是全局物体,这个Form对象(实现HTMLFormElement接口在W3CDOM中),在作用域链中。

但是,此处引用的窗体控件对象由border不可调用(不实现ecmaScript-内部的[[Call]]方法或实现它,以便在调用时抛出异常)。因此,如果您试图用border(this.value)..TypeError抛出异常,您应该在脚本控制台中看到这个异常(比如Chromium16.0.912.77[Developer Build 118311 linux]的开发工具中的“TypeError:边框不是函数”)。

20世纪90年代,Netscape的竞争对手微软(Microsoft)不得不将该功能复制到MSHTML DOM因此,为Netscape编写的代码也将在InternetExplorer(3.0)中运行,JScript(1.0)。微软的竞争对手也出于同样的原因将其复制到DOM实现中。它成为了准标准(现称“DOM级0").

然后是DOMLevel2HTML规范,这是当时标准化和扩展现有DOM实现的通用特性的持续努力。自2003-01-09年度起获W3C推荐,ECMAScript语言绑定指定HTMLCollections可以通过它们的名称访问。 ID使用括号属性访问器语法。[],相当于调用namedItem()方法对象的HTMLCollection接口。

form窗体中窗体控件的元素对象和元素对象是HTMLCollection在W3C DOM中,HTMLDocument::formsHTMLFormElement::elements分别。但是为了在浏览器中向后兼容,

document.forms["myForm"].elements["myControl"]

需要等价物

document.myForm.myControl

因此,最迟在W3CDOMLevel2HTML接口的实现中,这个特性开始应用于具有ID的元素 (id属性值)(例如,在Chrome中可以看到)。

因此,16年前在JavaScriptDOM中引入的方便特性至今仍像客户端DOM脚本中的bug一样咬你一口。

如果避免对窗体控件和窗体使用相同的名称或ID,将其用作用户定义函数的标识符,并且已用于内置窗体属性(如actionsubmit,和reset),这就不再是什么问题了。此外,对函数及其参数之一使用相同的标识符也是个坏主意,因为这使得函数对象无法从函数内部访问(函数上下文的变量对象位于其作用域链的第一位)。


查看完整回答
反对 回复 2019-06-29
  • 3 回答
  • 0 关注
  • 626 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信