我有两个几乎相同的简单JS小提琴调用选择更改的函数.在这两种情况下,函数名称与选择ID相同,但由于某种原因,第一个小提琴工作正常,第二个失败,出现JavaScript错误is not a function:
http://jsfiddle.net/AZkfy/7/ - 在FF9(Linux),Chromium 16(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>
Run Code Online (Sandbox Code Playgroud)
和
http://jsfiddle.net/cYVzk/ - 在FF9(Linux),Chromium 16(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>
Run Code Online (Sandbox Code Playgroud)
首先,我不明白为什么第一个工作正常,第二个工作失败.
第二 - 有关于冲突的JS函数名称和元素ID的JS规范或限制吗?
Poi*_*ars 63
这是源自JavaScript 1.0到1.3的遗留范围链问题,当时编程语言与我们现在称之为DOM API(当时的"动态HTML")之间没有区别.
如果表单控件(此处为:select元素)是表单(form元素的后代)的一部分,那么Form表示该form元素的对象在控件的事件处理程序属性值的代码范围链中是第三个 - 第二个 -接下来是表单控件对象本身,接下来是该代码的变量对象).
JavaScript™由Brendan Eich(当时在Netscape)设计,作为一种易于初学者使用的编程语言,可以很好地与HTML文档一起使用(作为Sun Java的补充;因此名称太混乱了).因为在早期语言和(Netscape)DOM API是一体的,这个(过度)简化也适用于DOM API:一个Form对象具有包含在表单中的控件的名称,它表示为其属性的名称参考相应的表单控件对象.IOW,你可以写
myForm.border
Run Code Online (Sandbox Code Playgroud)
这是符合标准(W3C DOM Level 2 HTML)的专有速记,但同样是向后兼容的
document.forms["myForm"].elements["border"]
Run Code Online (Sandbox Code Playgroud)
现在,如果你在事件处理程序使用表单控件的名称属性的表单控件的值的形式,像
<form …>
<… name="border" onchange='border(this.value)' …>
</form>
Run Code Online (Sandbox Code Playgroud)
就像你写了半专有的一样
<form …>
<… name="border" onchange='this.form.border(this.value)' …>
</form>
Run Code Online (Sandbox Code Playgroud)
或符合标准
<form …>
<… name="border" onchange='this.form.elements["border"](this.value)' …>
</form>
Run Code Online (Sandbox Code Playgroud)
因为一个潜在的全球border()功能是的属性的ECMAScript其去年来的时候,全局对象之后的Form对象(实施对象HTMLFormElement在W3C DOM接口),作用域链.
但是,此处引用的表单控件对象border不可调用(不实现ECMAScript内部[[Call]]方法或实现它,以便在调用时抛出异常).因此,如果您尝试使用该对象调用border(this.value),TypeError则会抛出异常,您应该在脚本控制台中看到该异常(例如Chromium 16.0.912.77的Developer Tools中的"TypeError:border is not function")[Developer Build 118311 Linux]) .
Netscape在20世纪90年代的竞争对手微软不得不为MSHTML DOM复制该功能,以便为Netscape编写的代码也可以在Internet Explorer(3.0)中运行,使用JScript(1.0).并且微软的竞争对手将其复制到他们的DOM实现中的原因完全相同.它成为准标准(现在称为" DOM Level 0 ")的一部分.
随后出现了DOM Level 2 HTML规范,这是继续努力标准化和扩展当前现有DOM实现的常见功能.自2003-01-09以来的W3C建议书,其ECMAScript语言绑定指定HTMLCollections的项目可以通过其名称或 ID使用括号属性访问器语法[... 来访问],相当于调用实现该接口的对象的namedItem()方法HTMLCollection.
form元件对象和表单的表单控件元素对象的项目HTMLCollection在W3C DOM S,HTMLDocument::forms和HTMLFormElement::elements分别.但是为了在浏览器中向后兼容,
document.forms["myForm"].elements["myControl"]
Run Code Online (Sandbox Code Playgroud)
需要等同于
document.myForm.myControl
Run Code Online (Sandbox Code Playgroud)
因此,最近实现了W3C DOM Level 2 HTML接口,此功能也开始应用于具有ID(id属性值)的元素(例如,可以在Chromium中看到).
因此,16年前JavaScript™中引入的便利功能仍然让您感觉像是当今客户端DOM脚本中的一个错误.
如果避免使用相同的名称或ID为表单控件和您作为用户定义的函数标识符使用的形式,并且已经用于内置形式属性(比如action,submit和reset),那么该变小的问题的.此外,对函数使用相同的标识符并使用其中一个参数(使代码混淆)使得函数对象在函数内不可访问是一个坏主意(函数上下文的变量对象首先出现在其作用域链中) ).
IE会自动var ID = domElement;为每个DOM-Element在全局空间中保留一个ID.其他一些浏览器采用了此行为.
始终尽量避免使用相同的ID和varnames!或者,在JS中使用您自己的命名空间以避免冲突.
编辑:
我不知道为什么你的一个例子失败了,而另一个例子有效.它可能是一个简单的执行时间/执行顺序 - 由包装引起的<form>.