LoginSignup
gackun
@gackun

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

JavaScriptでonload時にp要素のinnerHTMLを変更できません

解決したいこと

プログラミング初心者でJavaScriptの初歩的な学習をしています。
ページ読み込み時にp要素の値を換えようとしたところエラーが発生しています。
原因を教えていただきたいです。

発生している問題・エラー

Uncaught TypeError: Cannot set property 'innerHTML' of null

該当するソースコード

<script>
    var myfunc = function(){
       document.getElementById("p").innerHTML = "test";
    };
    window.onload = myfunc();
</script>
<p id="p"></p>

自分で試したこと

innerHTMLプロパティが無いみたいなエラーだと思い、p要素が読み込まれる前にinnerHTMLを参照していることが原因だと考え、p要素の下にscript要素を記述した所意図した動作になりました。
(まずはこの理解があっているのか知りたいです)

<p id="p"></p>
<script>
    var myfunc = function(){
       document.getElementById("p").innerHTML = "test";
    };
    window.onload = myfunc();
</script>

また、p要素の前にscript要素を記述した状態のまま関数を即時関数の中に入れた所、意図した動作をしました。
こちらはなぜエラーが起きないのか理解できていません。
(つぎにこのプログラムが動いている理由を知りたいです)

<script>
    var myfunc = function(){
       document.getElementById("p").innerHTML = "test";
    };
    window.onload = function(){myfunc()};
</script>
<p id="p"></p>

最後に、window.onloadはページの読み込み後に実行されるものだと認識しているのですが、それならp要素は読み込まれているはずなのに、なぜエラーになってしまうのでしょうか。
(できればこの解説もしていただきたいです)

みなさまのお知恵を拝借できれば幸いです。

1

1Answer

1つ目のソースコード

<script>
    var myfunc = function(){
       document.getElementById("p").innerHTML = "test";
    };
    window.onload = myfunc();
</script>
<p id="p"></p>

window.onload = myfunc(); では、 myfunc 関数を呼び出してその返り値(ここでは undefined)を window.onload に代入しています。ブラウザが HTML を上から読んでいってこの行に到達したときに myfunc 関数を呼び出し、その中の document.getElementById("p") が実行されることになりますから、この行より後に書かれている p 要素は当然見つかりません。2つ目のソースコードが動くのはこの行が p 要素の下に移動したからです。

window.onload = myfunc; と修正すれば、意図通り onload のタイミングで myfunc 関数が呼び出されるようになります。

なお、3つ目のソースコードの function(){myfunc()} は即時関数になっていません。即時関数とは (function() { ... })() の形で、匿名関数をその場で呼び出す書き方のことですが、ここでは呼び出していないためにただの匿名関数になっています。「myfunc() を呼び出す匿名関数」が onload のタイミングで呼び出された結果、意図した動作になっています。

4

Comments

  1. @gackun

    Questioner
    詳しく解説していただきありがとうございます。
    とても分かりやすかったです。
    一つだけ疑問があるのですが、なぜmyfunc()をmyfuncとすると動作するのか、教えていただけないでしょうか。
  2. myfunc 変数には関数オブジェクト(関数を表す実体)が入っています。関数オブジェクトはコードを含んだ指示書のようなものだと思ってください。 myfunc() のようにカッコをつけて呼び出すと「myfunc に入った指示書の内容を今すぐ実行せよ」とブラウザに命令することになります。実行したタイミングで p 要素が存在しなければ動作しないのは説明した通りです。

    逆に言えばカッコをつけなければ指示書の内容は実行されません。 window.onload = myfunc; と書けば、「myfunc に入った指示書を渡しておくから、ページの読み込みが終わったら実行するように」と伝えることができます。
  3. @gackun

    Questioner
    腑に落ちてスッキリしました。
    優しい言葉で説明していただき理解しやすかったです。
    本当にありがとうございました。

Your answer might help someone💌