gpt4 book ai didi

javascript - 为什么JS函数名和元素ID冲突?

转载 作者:IT王子 更新时间:2023-10-29 03:08:35 26 4
gpt4 key购买 nike

我有两个几乎相同的简单 JS fiddle ,在选择更改时调用函数。在这两种情况下,函数名称都与 select ID 相同,但由于某种原因,第一个 fiddle 工作正常,第二个失败并出现 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>



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>

第一 我不明白为什么第一个工作正常,而第二个失败。

第二 - 是否有关于冲突的 JS 函数名称和元素 ID 的任何 JS 规范或限制?

最佳答案

这是一个遗留范围链问题,起源于 JavaScript 1.0 到 1.3,当时编程语言和我们现在称为 DOM API(当时的“动态 HTML”)之间没有区别。

如果您的表单控件(此处:select 元素)是表单(form 元素的后代)的一部分,则 Form代表 form 的对象元素是控件的事件处理程序属性值中代码作用域链中的第三个下一个(第二个下一个是表单控件对象本身,下一个是该代码的变量对象)。

JavaScript™ 是由 Brendan Eich(当时在 Netscape)设计的,是一种易于初学者使用的编程语言,并且可以很好地处理 HTML 文档(作为 Sun 的 Java 的补充;因此这个名称总是令人困惑)。因为在早期语言和 (Netscape) DOM API 是一回事,这种(过度)简化也适用于 DOM API:A Form object has the names of the controls contained in the form that it represents as the names of its properties that refer to the corresponding form control objects . IOW,你可以写

myForm.border

这是符合标准的专有简写 ( W3C DOM Level 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 之后对象(在 W3C DOM 中实现 HTMLFormElement 接口(interface)的对象),在作用域链中。

但是,这里引用的表单控件对象是 border不可调用(不实现 ECMAScript 内部 [[Call]] 方法或实现它以便在调用时抛出异常)。因此,如果您尝试使用 border(this.value) 调用对象, TypeError抛出异常,您应该在脚本控制台中看到(例如 Chromium 16.0.912.77 [Developer Build 118311 Linux] 的开发人员工具中的“TypeError: border is not a function”)。

1990 年代 Netscape 的竞争对手 Microsoft 不得不为 MSHTML DOM 复制该功能。这样为 Netscape 编写的代码也可以在 Internet Explorer (3.0) 中运行,带有 JScript (1.0)。微软的竞争对手出于完全相同的原因将其复制到他们的 DOM 实现中。它成为准标准的一部分(现在称为“ DOM Level 0”)。

然后是 DOM Level 2 HTML 规范,这是对当时现有 DOM 实现的通用功能进行标准化和扩展的持续努力。自 2003-01-09 以来的 W3C 建议,其 ECMAScript Language Binding指定 HTMLCollection 的项目s 可以通过他们的名字或 访问编号 使用括号属性访问器语法 [] ,相当于调用 namedItem() method实现 HTMLCollection 的对象的界面。
form表单中表单控件的元素对象和元素对象是 HTMLCollection的项目W3C DOM 中的 s, HTMLDocument::forms HTMLFormElement::elements , 分别。但是为了在浏览器中向后兼容,
document.forms["myForm"].elements["myControl"]

需要等价于
document.myForm.myControl

所以,随着最晚 W3C DOM Level 2 HTML 接口(interface)的实现,这个特性开始应用于 ID 为 的元素( id 属性值)也是如此(例如,可以在 Chromium 中看到)。

因此,16 年前在 JavaScript™ 中引入的便利特性今天仍然像客户端 DOM 脚本中的错误一样咬你。

如果您避免对用作用户定义函数标识符的表单控件和表单使用相同的名称或 ID,并且已用于内置表单属性(如 actionsubmitreset) ),那么这就不那么重要了。此外,为函数使用相同的标识符及其参数之一是一个坏主意(将混淆代码放在一边)使函数对象无法从函数内部访问(函数上下文的变量对象首先出现在其作用域链中) )。

关于javascript - 为什么JS函数名和元素ID冲突?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9158238/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com