今回もHTMLでJavaScriptファイルを読み込むときの注意すべきポイントについての記事になります。
前回の記事「HTMLでJavaScriptの読み込み時に気をつけること【ページ表示を早める】」ではJavaScriptの読み込み位置を変えることで表示速度を早くすることを説明しました。
今回は複数のJavaScriptファイルを読み込む時に読み込む順番を意識しないと「うまく動かないこともある」ということについて解説します。
複数ファイル読み込もうとしているんだけど、「Uncaught ReferenceError: 〇〇 is not defined」ってなってうまく動かない。
何が原因でJavaScriptが途中でエラーになって処理が止まってしまうのかわからない。
今回の記事ではこのような問題でつまづいている・つまづいたことがある方にピンポイントの内容となります。
上記のような問題に直面したことない方でも、まだJavaScriptの学習を始めたばかりの方は、今回の記事を読むことで同じ問題につまづいた時にすぐに解決できるようになります。
今回の記事は次の内容で話を進めていきます。
- JavaScriptファイルの依存関係を考える
- JavaScriptファイル読み込みの成功例と失敗例
それでは1つ目の内容から話していきます。
目次
JavaScriptファイルの依存関係を考える
そもそもなんでファイル分割するの?
まずはじめに確認させてください。
JavaScriptは1つのファイルに全ての処理を書き込むことが出来るのになぜファイルを複数に分割する必要があるのでしょうか?
答えを言うと、ファイルの分割を行うことで次のようなメリットがあります。
逆に、ファイル分割を行わず1つのファイルに処理を全て書いてしまった場合のデメリットは次のとおりです。
- コードが肥大化し数千行(プロジェクトによっては数万行)となり、どこに何があるかすぐに見つけられない(メンテナンス性の低下)
- 他のプロジェクトで使い回せない(プロジェクトごとにゼロから同じ機能を作る)
上記のメリット・デメリットで上げた理由から、かなり小さなプロジェクトでない限り、アプリケーション開発する際には基本的にファイル分割する場面がたくさん出てきます。
ファイル分割するときの注意点
今回の記事タイトルにも書いていますが、ファイル分割した際には「依存関係」というものに注意する必要が出てきます。
例えば、JQueryを使ってフロントエンド開発をしているとします。
JQueryのファイルを読み込まずに「$(‘#id’)」と書いて、特定のHTML要素を取得しようとしても「Uncaught ReferenceError: $ is not defined」とエラーになります。
このエラーが起きる理由は「コードがJQueryに依存している」からです。
このようにファイル分割をしたら、利用する機能を実装しているJavaScriptファイルを読み込む必要があります。(例: JQueryを読み込む)
しかし、必要なファイルを単純に何も考えずに読み込んだとしてもうまく動かないことがあります。
それでは実際にどのように読み込んだらうまく動かないのか、逆にどのようにしたらうまく動くのかサンプルコードを使って確認していきましょう。
JavaScriptファイル読み込みの成功例と失敗例
まずはじめに、今回の例で共通して使うJavaScriptの2ファイルのサンプルコードを次にまとめます。
- person.js (依存するファイルはない。)
- main.js (person.jsとJQueryに依存している。(2ファイルを使う))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
class Person { /** * new Person('つよぽん') => Personインスタンスが出来て、 * Personクラス内で定義されているメソッド(今回の場合はintroduceMyselfのみ)を実行することが出来る * 例: * const tsuyopon = new Person('つよぽん'); * tsuyopon.introduceMyself(); // => 私の名前はつよぽんです。 * * @param {string} name */ constructor(name, age) { this.name = name; } /** * @returns {string} */ introduceMyself() { // テンプレート文字列を使うことで文字列内に変数を埋め込むことが出来ます。 // https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/template_strings#Description return `私の名前は${this.name}です。`; } } |
1 2 3 |
const person = new Person('つよぽん'); const $introductionArea = $('#introduction-area'); $introductionArea.text( person.introduceMyself() ); |
JavaScriptファイル読み込み失敗例
それでは失敗例から見ていきましょう。
次のHTMLのサンプルコードで注目していただきたいのは14行目, 15行目のmain.jsとperson.jsのファイル読み込みの順番です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>自己紹介</title> </head> <body> <h1>自己紹介</h1> <p id="introduction-area">ここに自己紹介文を入れる(JavaScriptで文字列を差し替える)</p> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <script src="./main.js"></script> <script src="./person.js"></script> </body> </html> |
上記コードの実行結果は次の画像になります。
上記HTML内でmain.jsは14行目、person.jsは15行目で読み込まれています。
HTMLは上から順番に処理を実行します。14行目のmain.jsを読み込み、main.jsの1行目から最後の行まで実行が完了してから、15行目のperson.jsの読み込みを始めます。
しかし、main.jsの1行目でperson.js内で定義されている「Person」クラスを利用していますが、この時点ではperson.jsの読み込みは始まっていないので「Person」はまだ定義されていない状態です。
そのため、上に貼った実行結果の画像のエラーのように「Uncaught ReferenceError: Person is not defined」というエラーが発生して処理が途中で止まってしまったのです。
初心者にとって簡単なエラーでも原因を見つけるのが難しかったりするのでエラーの解決方法を説明します。
上に貼った実行結果の画像はデベロッパーツールのコンソール画面で、エラーになると赤背景・赤文字でエラー内容が出力されます。
エラー内容は英語で表示されるのでわからない単語があれば「weblio」や「アルク」などを使って意味を調べるとエラー内容がわかります。
また、どのファイルの何行目でエラーが起きたのかもエラー出力の右側で確認できます。
今回の場合だと「main.js:1」とあるので、main.jsの1行目でエラーが起きているというのがわかります。
JavaScriptファイル読み込み成功例
今回のエラーを解決する場合は、main.jsの読み込みを開始する前にperson.jsの読み込みを先に完了させれば良いので、次のようにmain.jsとperson.jsの順番を入れ替えれば解決します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>自己紹介</title> </head> <body> <h1>自己紹介</h1> <p id="introduction-area">ここに自己紹介文を入れる(JavaScriptで文字列を差し替える)</p> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <script src="./person.js"></script> <script src="./main.js"></script> </body> </html> |
実行結果は次のとおりになります。
main.jsのファイル依存関係の問題が解決されて、main.jsの3行目で行っている文字列(p要素)の置換が成功して「私の名前はつよぽんです。」という文字に置き換わりました。
上の画像左側にある「自己紹介」と書かれている下の文字列が今回置換した箇所になります。(失敗例に貼った実行結果画像の文字列と異なるのがわかるかと思います。)
まとめ
ここまで話してきた内容をあらためてまとめると次のようになります。
- ファイル分割をした際には、ファイルの依存関係が発生する場合がある
- 依存関係がある場合、まず先に依存される側のファイルを読み込む必要がある
- 今回の例:
- 依存されるファイル: person.js, JQuery
- 今回の例:
- 依存されるファイルの読み込みが完了してから、依存するファイルを読み込む
- 今回の例:
- 依存するファイル: main.js
- 今回の例:
ここまで話してきたように、ファイル分割した際には依存関係が正しく解決されているのかを意識してJavaScriptファイルの読み込みの順番には気をつけましょう。