Ответ 1
Это устаревшая проблема с цепочкой поставок, исходящая с JavaScript 1.0 до 1.3, когда не было различий между языком программирования и тем, что мы теперь называем DOM API (далее "Динамический HTML" ).
Если ваш элемент управления формой (здесь: a select
) является частью формы (потомок элемента form
), то объект form
, который представляет элемент form
, является третьим рядом в целая цепочка кода в значениях атрибута управляющего события-обработчика (второй-следующий - сам объект управления формой, следующий - переменный объект этого кода).
JavaScript ™ был разработан Бренданом Эйхом (затем в Netscape) в качестве языка программирования, который прост в использовании для новичков, и это хорошо работает с документами HTML (как дополнение к Sun Java, а значит, и к запутанному имени). Поскольку в те ранние годы язык и (Netscape) DOM API были одним, это (более) упрощение, применяемое к API DOM: Объект form
имеет имена элементов управления, содержащиеся в форме, которую он представляет, как имена его свойств, которые относятся к соответствующим объектам управления формой. IOW, вы можете написать
myForm.border
который является собственной стенографией стандартно-совместимых (W3C DOM Level 2 HTML), но одинаково обратная совместимость
document.forms["myForm"].elements["border"]
Теперь, если вы используете имя элемента управления формы в значении атрибута event-handler элемента управления формы в форме, например
<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
в DOM W3C), в цепочке областей видимости.
Однако объект управления формой, указанный здесь border
, не может быть вызван (не реализует ECMAScript-внутренний метод [[Call]]
или реализует его так, чтобы он вызывал исключение при вызове). Поэтому, если вы пытаетесь вызвать объект с помощью border(this.value)
, генерируется исключение TypeError
, которое вы должны увидеть в консолях script (например, "TypeError: border не является функцией" в Developer Tools of Chromium 16.0. 912.77 [Developer Build 118311 Linux]).
Microsoft, конкуренту Netscape в 1990-х годах, пришлось скопировать эту функцию для MSHTML DOM, чтобы код, написанный для Netscape, также запускался в Интернете Explorer (3.0), JScript (1.0). И конкуренты Microsoft скопировали их в свои реализации DOM по той же причине. Он стал частью квазистандартного (теперь называемого DOM Level 0").
Затем появилась DOM Level 2 HTML Specification, продолжающаяся попытка стандартизации и расширения общих функций существующих реализаций DOM в то время. Рекомендация W3C с 2003-01-09, ее привязка языка ECMAScript указывает, что элементы HTMLCollection
могут быть доступны по их имени или ID с синтаксисом доступа к атрибуту bracket [
... ]
, что эквивалентно вызову метода namedItem()
реализации объекта интерфейс HTMLCollection
.
form
Объекты элементов и объекты элементов для элементов управления формами в формах являются элементами HTMLCollection
в DOM W3C, HTMLDocument::forms
и HTMLFormElement::elements
, соответственно. Но для обратной совместимости в браузерах
document.forms["myForm"].elements["myControl"]
должен быть эквивалентен
document.myForm.myControl
Итак, с реализацией интерфейсов HTML W3C DOM Level 2, эта функция начала применяться к элементам с атрибутом ID (id
) (что можно увидеть в Хром, например).
В результате удобная функция, введенная в JavaScript ™ 16 лет назад, все еще укусит вас как ошибку на скриптах DOM на стороне клиента.
Если вы не используете одно и то же имя или идентификатор для элементов формы и форм формы, которые вы используете в качестве идентификатора определяемых пользователем функций и которые уже используются для встроенных свойств формы (например, action
, submit
и reset
), тогда это становится проблемой. Кроме того, это плохая идея использовать один и тот же идентификатор для функции и один из ее аргументов как (путающий код в сторону), что делает объект функции недоступным изнутри функции (объект Variable объекта функции входит в первую очередь в своей цепочке видимости).