JSの関数名が要素IDと矛盾するのはなぜですか?

私は2つのほぼ同じシンプルなJSのfiddlesを選択変更の関数を呼び出している。関数名はどちらの場合もselect IDと同じですが、何らかの理由で最初のフィドルが正常に動作し、2番目のフィードバックがJavaScriptエラー is not function

http://jsfiddle.net/AZkfy/7/ - works fine in FF9 (Linux), Chromium 16 (Linux), IE8 (Windows):

<script>
    function border(border) { alert(border); }
</script>


そして

http://jsfiddle.net/cYVzk/ - fails in FF9 (Linux), Chromium 16 (Linux), IE8 (Windows):

<script>
    function border(border) { alert(border); }
</script>

<form>

</form>

First of all I fail to understそして why the first one works fine, そして the second one fails.

Second - are there any JS specifications or restrictions regarding the conflicting JS function names そして element ID?

39
追加されたブラウザのバージョン
追加された 著者 Oleg Mikheev,
私にとっては2番目の作品と1番目の作品は失敗します(クロムでテスト)。あなたのブラウザを追加できますか?
追加された 著者 Grrbrr404,
これは私のために働く jsfiddle.net/ZdhRe
追加された 著者 Grrbrr404,

2 答え

これは、JavaScript 1.0から1.3に由来する従来のスコープチェーンの問題で、プログラミング言語とDOM API(現在は「ダイナミックHTML」)と呼ばれているものが区別されませんでした。

フォームコントロール(ここでは select 要素)がフォーム( form 要素の子孫)の一部である場合、 Form コントロールのイベントハンドラの属性値のコードのスコープチェーン内の3番目にnextの form 要素を表します(次に、フォームコントロールオブジェクト自体、次にそのコードの変数オブジェクト)。

JavaScript™ was designed by Brendan Eich (then at Netscape) as a programming language that is easy to use for beginners and that works well with HTML documents (as complement to Sun's Java; hence the ever-confusing name). Because in those early days language and (Netscape) DOM API were one, this (over)simplification applied to the DOM API as well: 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, you can write

myForm.border

これは標準に準拠した( W3C DOM Level 2 HTML < a>)でも同様に後方互換性があります

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 インタフェースを実装するオブジェクト)をスコープチェーン内で

ただし、ここで border で参照されるフォームコントロールオブジェクトは、コール可能ではありません(ECMAScript内部の [[Call]] メソッドを実装していないか、呼び出されたとき)。したがって、 border(this.value)でオブジェクトを呼び出そうとすると、 TypeError の例外がスローされます。 Chromium 16.0.912.77の開発者ツール[Developer Build 118311 Linux]の機能ではありません)。

1990年代にNetscapeのライバルであったMicrosoftは、 MSHTML DOM を使用して、Netscape用に作成されたコードもInternet Explorer(3.0)で JScript (1.0)。そして、Microsoftの競合他社はまったく同じ理由でDOM実装にそれをコピーしました。それは準標準(現在は「 DOM Level 0 ")。

その後、DOMレベル2のHTML仕様が発表されました。この仕様は、当時の既存のDOM実装の共通機能を標準化して拡張するための継続的な取り組みでした。 2003年1月9日以降のW3C勧告、その ECMAScript言語バインディングでは、 HTMLCollection の項目にブラケットプロパティアクセサの構文を使用してまたは ID > [ ... ] を使用して、 namedItem()

form element objects and element objects for form controls in forms are items of HTMLCollections in the W3C DOM, HTMLDocument::forms and HTMLFormElement::elements, respectively. But for backwards compatibility in browsers,

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

同等する必要があります

document.myForm.myControl

W3C DOM Level 2 HTMLインターフェイスの実装により、この機能は ID id 属性値)にも適用され始めました。例えば、Chromiumに見られる)。

As a result, the convenience feature introduced in JavaScript™ 16 years ago still bites you like a bug in client-side DOM scripting today.

ユーザー定義関数の識別子として使用するフォームコントロールとフォームに同じ名前またはIDを使用することを避け、既に組み込みフォームプロパティ( action reset )、これが問題になることはありません。また、関数内で関数オブジェクトにアクセスできないように(関数のコンテキストの変数オブジェクトがスコープチェーン内で最初に来るように) )。

60
追加された
@Christophあなたは歓迎です:) IDについての質問だったので、これをさらに調べて、W3C DOM 2 HTMLがこの問題を要素IDにどのように関連づけているかの説明を追加しました。また、フォームオブジェクトは、スコープチェーン内で 3番目であることにも注意してください。曖昧さがない場合は、 value (!)だけを this.value に書く必要はありません。
追加された 著者 PointedEars,

IEは自動的に ID を持つ各DOM要素のグローバルスペースに var ID = domElement; を予約します。他の一部のブラウザはこの動作を採用しました。

常に同じIDと名前を使用しないようにしてください!あるいは、JS内で独自の名前空間を使用して、衝突を避けることもできます。

編集:

I don't know why one of your examples fails, while the other one works. It might be a simple timing/order of execution -issue caused by the wrapping <form>.

5
追加された
ありがとう、しかし、私はまだ最初のフィドルがうまくいく理由を理解していない...
追加された 著者 Oleg Mikheev,
私の答えで言及したように、私はフォームがdom要素によってvarの占有を遅らせるかもしれないと仮定します。したがって関数はvarに最初に割り当てられ、後でdom要素によってオーバーライドされます。
追加された 著者 Christoph,
@Mathias私はこれがいくつかの要素のname属性にも当てはまることは知らなかった。ですから、問題は実際には、option要素の変数の作成は、グローバルオブジェクトに付加された関数をシャドーイングすることです。
追加された 著者 Christoph,
変更のために、これはスコープチェーン内のグローバルホストオブジェクトのプロパティを介してアクセス可能な名前付き/ IDの要素に対するMSHTMLのオブジェクトを作ることとは関係がなく、タイミングとは関係ありません。これは従来のスコープチェーンの問題であり、標準コンプライアンスモードでも発生します(ただし、IE以外のいくつかのブラウザでは名前/ IDの問題は発生しません)。
追加された 著者 PointedEars,
@Christoph 選択要素のプロパティの作成。
追加された 著者 PointedEars,
@Christophあなたが何を記述しているかはHTML5仕様書に記載されています: whatwg.org/specs/web-apps/current-work/multipage/… しかし、将来削除される可能性があります
追加された 著者 Mathias Bynens,
JavaScript - 日本のコミュニティ
JavaScript - 日本のコミュニティ
2 参加者の

日本人コミュニティのjavascript