背景
今受けている大学の授業でJavaScriptを扱っている。
その授業で window.open
という関数を用いて新しいウィンドウを開いたり閉じたりする関数を作るという課題が出ているのだが、この課題に取り組んでいる友人がプログラムが動かないと言っていたので、コードを見たところ下のようなコードを書いていた。
<script> function open(a) { window.open(a); } <script> <body> <input type="button" onclick="open('~~~~')"> </body>
このコードが動かない理由について下で書いていく。
何故動かないのか
JavaScriptは関数の外に作成した変数や関数、例えばscriptタグの中に直接書き込んだ変数や関数はグローバル変数やグローバル関数となる。
下のコードは変数message
と関数hello
をグローバルな変数や関数として宣言した例だが、window.message
やwindow.hello()
とやってもmessage
変数の参照やhello
関数の実行が出来る。
<script> var message = "Hello, world!"; function hello() { alert("hello"); } alert(window.message); // "Hello, world!"とアラートが出る window.hello(); // hello関数が実行され、helloとアラートが出る <script>
何故これで実行出来るのかというと、実はJavaScriptではグローバル変数やグローバル関数を作るということは、グローバルオブジェクトのプロパティとして定義するということを意味する。グローバルオブジェクトとはその実行環境の一番トップにあるオブジェクトのことだが、ここではwindow
オブジェクトのことだと思えばいい。
なので関数の外でvar message;
やfunction hello() {}
はwindow
オブジェクトのプロパティやメソッドを宣言していることと同じなのだ。その為、window.message
やwindow.hello()
で変数の参照や関数の実行が出来る。
このことを考えると先程のコードが動かない理由が説明できて
<script> // window.openの再定義 function open(a) { // 再定義された window.openを呼び出す window.open(a); } <script> <body> // クリックしたが最後無限ループ地獄へ <input type="button" onclick="open('~~~~')"> // エラーが出る </body>
function open(a) ~
の記述で、既に存在しているwindow.open
関数を再定義する形になる。その再定義したopen
関数でwindow.open
を呼んでいるのでいつまでも再帰呼び出しがされ、無限ループが発生する。
ちなみにChromeではUncaught RangeError: Maximum call stack size exceeded(…)
というエラーが発生する。これはスタックオーバーフローのエラーで、JavaScriptで再帰処理を行ったときにを行いすぎたときに見かけるエラーである。
FirefoxはInternalError: too much recursion
とエラーが出た(まんまだな……)。
まとめ
JavaScriptを理解してないとこういうこともある。割と初級者がハマることで「JavaScript グローバル汚染」とかでググると似たようなことが書いてある記事が一杯ある。
一応授業的にはこれを回避する予防線を張ってるみたいで、
ウィンドウを生成する関数createNewWindow ("URL")を作ること.また,引数として表のURLの何番目(n)かを受け取り,対応するウィンドウを閉じる関数closeWindow (n)を作ること.
と書いてあった。でも説明の仕方を考えればグローバルオブジェクトのことを説明できたと思うしフォローのやり方はもっとあるんじゃないかなあと思う。*1
参考
JavaScriptについて本格的に勉強したいと思ったらここだけを読むといいと思う。他のサイトが全く信用できないわけないないけどMDNは割と信用できる。
パーフェクトJavaScript (PERFECT SERIES 4)
- 作者: 井上誠一郎,土江拓郎,浜辺将太
- 出版社/メーカー: 技術評論社
- 発売日: 2011/09/23
- メディア: 大型本
- 購入: 24人 クリック: 588回
- この商品を含むブログ (12件) を見る
JavaScriptの本はサイ本とこの本しかよく知らない。だいぶ古い本になっちゃったけど言語仕様をわかりやすく書いてあるのでオススメではある。
*1:授業自体は様々な言語に触れて、色々なパラダイムを学ぼうというもの。JavaScriptはイベント駆動型プログラミングのテーマで扱われている。全4回しかなく、限られた時間で説明するために詳しくやらないのはわかる。わかるけど………