48321


本件、恥を忍んでお聞きします。JSについて、一から出直そうと考えていて

[code]

    document.getElementById("text-button").onclick = function() {
            document.getElementById("text").innerHTML = "クリックされた！";
            console.log("You're getting on my nerves!");
    };
    
[/code]

という外部JSを、以下のHTML①で読み込んだ際は 無事動作します。世間で推奨されるbodyタグ内最下部での読み込みです。【事例Ａ】

[code]

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>トライアル</title>
        <link rel="stylesheet" type="text/css" href="css/test_style.css">
    
    </head>
    <body>
    <?php
    
    ?>
    <div id="text-button"><p id="text">クリック</p></div>
    <script type="text/javascript" src="js/test.js"></script>
    </body>
    </html><!DOCTYPE html>
    
[/code]

尚、以下HTML②のように、外部JSの読み込み位置をheadタグ内に変更するとJSは動作はしませんでした。【事例Ｂ】

[code]

    <html>
    <head>
        <meta charset="UTF-8">
        <title>トライアル</title>
        <link rel="stylesheet" type="text/css" href="css/test_style.css">
        <script type="text/javascript" src="js/test.js"></script>
    </head>
    <body>
    <?php
    
    ?>
    <div id="text-button"><p id="text">クリック</p></div>
    
    </body>
    </html>
    
[/code]

それでは...と思いHTML自体はそのままを維持（headタグ内で外部JSを読み込む）し、外部JS内部を以下のように変更しました。  
自分としては「DOM要素の読み込みが完了してから動作させる」の意味合いで、`$(function(){`を追加したつもりでしたが
やはりJSは動作してくれません。【事例Ｃ】

[code]

    $(function(){
        document.getElementById("text-button").onclick = function() {
            document.getElementById("text").innerHTML = "クリックされた！";
            console.log("You're getting on my nerves!");
        };
    });
    
[/code]

====回答のお願い====  
事例②のJSが動作しない理由として、JSが読み込まれる時点で該当要素がないから...みたいな説明をよく見るのですが、恥ずかしながら当方は理解できていません。JSがクリックイベントの記述なのでクリックイベント時点で、要素があるか否かが重要でないのか？と思ってしまうわけです。  
本件をどう理解すればよろしいのでしょうか？

事例③でもJSが動作しない理由を教えて頂けますでしょうか？  
`$(function(){`の本質の意味を捉えていないのかも知れません。  
JQueryの記述をしてしまえば 動くのかも知れませんが、しっかり理解したいので動作しなかった理由をご説明頂けますでしょうか？


CC BY-SA 4.0
2018-09-12T09:56:05.770
48316
2018-09-12T12:00:52.943
25696
question
javascript jquery
外部JSファイルの読み込み位置次第で　挙動が変わることについておさらいしたい


> JSがクリックイベントの記述なのでクリックイベント時点で、要素があるか否かが重要でないのか？

当たり前なことですが、あらかじめクリック時のイベントハンドラを登録しておかないことにはクリックしても何も実行されません。そしてこれも当たり前のことですが、対象の要素が定義されていなければ、クリック時のイベントハンドラの登録は行えません。  
結局、要素が定義されてから実際にクリックされまでの間のタイミングで登録行為が必要です。

> `$(function(){`の本質の意味を捉えていないのかも知れません。JQueryの記述をしてしまえば
> 動くのかも知れませんが、しっかり理解したいので動作しなかった理由をご説明頂けますでしょうか？

`$`は通常の変数であり、何も定義されていなければエラーが発生するだけです。また[jQuery](https://github.com/jquery/jquery/blob/master/src/exports/global.js)では

[code]

     window.jQuery = window.$ = jQuery;
    
[/code]

このように変数`$`を定義しています。このため、`$`は[`jQuery`関数](https://api.jquery.com/jQuery/)と同じ機能が提供されています。`jQuery`を読み込まずに似たようなことを実現するには[`window.onload`](https://developer.mozilla.org/ja/docs/Web/API/GlobalEventHandlers/onload)を使って

[code]

    window.onload(function(){
        document.getElementById("text-button").onclick = function() {
            document.getElementById("text").innerHTML = "クリックされた！";
            console.log("You're getting on my nerves!");
        };
    });
    
[/code]

とかできます。


CC BY-SA 4.0
2018-09-12T11:37:20.483
48320
2018-09-12T11:37:20.483
4236
48316
answer


**事例2** について、「JSが読み込まれる時点で該当要素がないから」という説明は合っています。  
これは確かに「クリックイベントの記述」ですが、実際に事例2のコードで行われていることは、「クリックイベントを **登録する**
」ということです。クリックイベントを登録することによって、その後その要素がクリックされたら関数が呼ばれるようになるのです。

ここで重要なことは、 **イベントを登録するためには登録先の要素を取得する必要がある**
という点です。登録するために要素が必要ということは、当然ながら、イベントを登録する時点（＝JSが読み込まれた時点）で該当要素が必要ということです。  
実際、これが事例2が動かなかった原因です。

実際、問題のソースコードはまず当該要素を **取得** し、それに対してイベントを **登録**
するコードになっています。取得部分は`document.getElementById("text-button")` であり、これはIDが`"text-
button"`である要素を取得するという意味です。そして、続く`.onclick = ...`という部分でその要素に対してイベントを登録しています。  
分かりやすいように、取得した要素を変数に入れるように書き直すと次のようになります。

[code]

    var button = document.getElementById("text-button");
    button.onclick = function() {
            document.getElementById("text").innerHTML = "クリックされた！";
            console.log("You're getting on my nerves!");
    };
    
[/code]

* * *

**事例3** が動かなかった理由については、`$`はJavaScript（正確にはDOM）にもともと存在するものではないことが理由ではないかと思います。

質問者さんもご存知の通り、`$`は確かに「DOM要素の読み込みが完了してから動作させる」というような意味で使えますが、これは`$`はJavaScript標準の機能ではなく
**jQuery** という **ライブラリ** の機能です。ですから、 **まずjQueryを読み込まなければ使えません** 。  
事例3のソースコードは、おそらく先に以下のようなHTMLでjQueryを読み込めば動くようになると思います。

[code]

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
    
[/code]

なお、参考として、ライブラリであるjQueryに頼らない、JavaScript（DOM）に標準の方法をお伝えします。以下のように`document`の`DOMContentLoaded`イベントを登録するのがよいでしょう。

[code]

    document.addEventListener("DOMContentLoaded", function(){
        document.getElementById("text-button").onclick = function() {
            document.getElementById("text").innerHTML = "クリックされた！";
            console.log("You're getting on my nerves!");
        };
    });
    
[/code]


CC BY-SA 4.0
2018-09-12T12:00:52.943
48321
2018-09-12T12:00:52.943
30079
48316
answer