インラインJavaScript(HTML)はどのように機能しますか?


129

これは悪い習慣だと知っています。可能な限り、このようなコードは記述しないでください。

もちろん、インラインJavascriptの巧妙なスニペットで問題にすばやく対処できる状況では、常に自分自身を見つけます。

次のようなものが書かれたときに何が起こるか(そして潜在的な落とし穴)を完全に理解するために、このクエリを追求しています。

<a href="#" onclick="alert('Hi')">Click Me</a>

私が知る限り、これは機能的には同じです

<script type="text/javascript">
   $(function(){ // I use jQuery in this example
       document.getElementById('click_me').onclick = 
           function () { alert('Hi'); };
   });
</script>
<a href="#" id="click_me">Click Me</a>

これから推定すると、属性に割り当てられた文字列onclickは、要素のクリックハンドラーに割り当てられた無名関数内に挿入されているようです。これは本当ですか?

私はこのようなことを始めているので:

<a href="#" onclick="$(this).next().fadeIn(); return false;">Display my next sibling</a> <!-- Return false in handler so as not to scroll to top of page! --> 

うまくいきました。しかし、これがどれだけのハックなのかはわかりません。から返されている明らかな関数がないため、疑わしく見えます!

あなたは尋ねるかもしれません、なぜあなたはこれをしているのですか、スティーブ?インラインJSは悪い習慣です!

正直なところ、ページの1つのセクションを変更するためだけにコードの3つの異なるセクションを編集するのにうんざりしています。特に、プロトタイプを作成して、それがまったく機能するかどうかを確認する場合は特にそうです。これは非常に簡単で、このHTML要素に特に関連するコードを要素で定義することも理にかなっています。2分後にこれがひどい、ひどい考えだと判断したとき、div全体(または何でも) )そして、私はページの残りの部分にぶら下がっている不思議なJSとCSSの束がたくさんないので、レンダリングが少し遅くなります。これは参照の局所性の概念に似ていますが、キャッシュミスではなく、バグとコードの膨張を調べています。


3
あなたは正しい、それは無名関数です。
ハムリン

1
クエリを#click_meDOMreadyイベントにフックするか、ノードの後に​​スクリプトを配置する必要があります。
ベルギ

1
コンソールで、を実行しますdocument.getElementById("click_me").onclick;。または警告します。関数内にあることがわかります。
D.ストラウト

回答:


96

ほぼ正しいですがthis、インラインコードに提供された値を考慮していません。

<a href="#" onclick="alert(this)">Click Me</a>

実際に近いです:

<a href="#" id="click_me">Click Me</a>
<script type="text/javascript">
document.getElementById('click_me').addEventListener("click", function(event) {
    (function(event) {
        alert(this);
    }).call(document.getElementById('click_me'), event);
});
</script>

インラインイベントハンドラーthisは、イベントのターゲットに等しく設定されます。インラインスクリプトで無名関数を使用することもできます

<a href="#" onclick="(function(){alert(this);})()">Click Me</a>

7
スクリプトはタグの後に置く必要があります。そうしないと、実行時にタグが存在しません。これを反映するように回答を変更することをお勧めします。
未定義

eventインラインでどのように伝播しますonclick='myFunction(event)'か?
オールドボーイ

9

あなたが持っているときにブラウザは何をしますか

<a onclick="alert('Hi');" ... >

「onclick」の実際の値を効果的に次のようなものに設定することです:

new Function("event", "alert('Hi');");

つまり、「イベント」パラメータを必要とする関数を作成します。(まあ、IEはそうではありません。それは、単なる単純な匿名関数のようなものです。)


2
ああ。そのため、実際に変数eventを使用してevent.target、インラインJSスニペットからイベント(およびを介した元の要素)を取得できます!涼しい。
Steven Lu

1
IEは実際にはeventパラメーターを渡しませんが、eventこの匿名関数内で使用すると、IEはそれを実際のイベントオブジェクトとして認識します。無名関数はwindowIE のオブジェクトのプロパティとして設定されるため、これはと表示されwindow.eventます。
rdleal

8

イベントハンドラー属性については、多くの悪い習慣が投げかけられているようです。悪い習慣とは、最も適切な場所で利用可能な機能を知り、使用することではありません。イベント属性は完全にW3Cで文書化された標準であり、それらについて悪い習慣はありません。これはインラインスタイルを配置することと同じです。インラインスタイルもW3Cで文書化されており、時々役立ちます。スクリプトタグで囲むかどうかに関係なく、同じように解釈されます。

https://www.w3.org/TR/html5/webappapis.html#event-handler-idl-attributes


2
ええ、私は同意する傾向があります。この特定の種類のインラインコードの使用が特定の状況で正当化される理由について、合理的な「理由」も提供しました。しかし、実際には、アプリ(Webアプリなど)が特定の複雑さになると(そして、通常、これに到達するのにそれほど時間も労力もかかりません)、HTML レイアウトコードスニペットが散りばめられている可能性があります。保守性の観点からは、アーキテクチャ的に健全でない。たとえば、HTMLファイル内でJSを直接コーディングし始めることでさえ、スパゲティフィケーションの滑りやすい傾斜を魅力的にしています。
Steven Lu

1
そしてそれは私が同意する一つの正当な正当な主張に対するものです。私は通常、インラインスクリプトを追加したり、その資料のスタイルを設定したりしません。しかし、人によって好みは異なります。たとえば、多くの場合、bodyセクションにスクリプトタグやスタイルタグを追加したいので、我慢できません。しかし、それは有効であり、それを好む人もいます。bad practice/spaghettification一部の縫い目はgood practice/structure、他の縫い目と同じです。
Daniel B

私はgithub.com/styled-components/styled-componentsを見てきましたが、たとえば、これをreactと組み合わせると、アプリのコンポーネントに関連付けられているすべてが1つの場所に(うまくいけば平和的に)実際に共存するようになります。そして、それは実際にひどくも見えません。進歩のように感じます。この観点から、インラインスタイルとコードをHTMLに詰め込むことは正しい方法ではありません(これまでのところ、JSコードにHTMLとスタイルを詰め込むことのようです)。
Steven Lu

5

あなたの質問に答える最良の方法は、実際にそれを見ることです。

<a id="test" onclick="alert('test')"> test </a> 

jsで

var test = document.getElementById('test');
console.log( test.onclick ); 

を見るとわかるように、consoleChromeを使用している場合は、IEとは少し異なりますが、渡されたイベントオブジェクトを使用して無名関数が出力されます。

function onclick(event) {
   alert('test')
}

インラインイベントハンドラに関するいくつかの点に同意します。はい、それらは簡単に書くことができますが、複数の場所でコードを変更する必要があるというあなたの意見に同意しません。コードを適切に構成している場合、これを行う必要はありません。


のようなもの<button onclick="login()"> test login </button>はプロトタイピングにはまったく問題ないと思います。ユーザーの操作が必要なものを今すぐテストしたいのですが、とにかく後でそれを削除するだけです。なぜあちこちに余分なコードを書くのですか?
ダッグナビット

これは追加のコードではなく、追加の匿名関数です。そして、それはすべての場所にあるわけではなく、実際にはすべて1か所のスクリプトタグにあります。
aziz punjani 2012年

「コードを適切に構成する」という同じ考え方を共有しているとは思えません。コア機能が実際に存在する場所でUIを「コア機能」にバインドすると、UIでそれらをバインドするよりも、カップリングの配置が悪いように思えます。私は通常、すべてのUIバインディングスタッフをコアスタッフとは別にしており、OPもそうかもしれないと感じています...
Dagg Nabbit

3

から返されている明らかな関数がないため、疑わしく見えます!

これは、オブジェクトのクリックイベントに関連付けられている匿名関数です。

なぜあなたはこれをしているのですか、スティーブ?

どうしてあなたはドイなのですか.....気にしないでください、あなたが言ったように、それは本当に広く採用されている悪い習慣です:)


3

コンソールでこれを試してください:

var div = document.createElement('div');

div.setAttribute('onclick', 'alert(event)');

div.onclick

Chromeでは、次のように表示されます。

function onclick(event) {
  alert(event)
}

...の非標準nameプロパティdiv.onclick"onclick"

したがって、これが匿名かどうかは、「匿名」の定義に依存します。空文字列var foo = new Function()であるのようなものと比較すると、次のようなものが生成されますfoo.namefoo.toString()

function anonymous() {

}

これは、Pointyの回答に対するコメントとして始まりましたが、実際にはコメントとして機能しませんでした。彼は本当にここでの最良の答えだと思います。
Dagg Nabbit、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.