5
0

More than 1 year has passed since last update.

【javascript】type="module"の時にグローバル変数を作る方法

Last updated at Posted at 2022-03-23

結論

window.globals = {変数名: 値}
は、javascript実行環境全体で使いまわすことができる。

そもそもの問題

type="module"でjavascriptを使っていると、「varを省略することでグローバル変数を作る」ことが出来ない。

だから、次のプログラムは動かない。

type="module"の苦悩
<html>
    <head>
        <script type="module">
        document.body = document.createElement("body");
        document.body.innerHTML = `
        <div id="カウンタ"></div>
        <div id="ボタンたち">
            <input type="button" value="++" onClick="画面.add(1)">
            <input type="button" value="--" onClick="画面.add(-1)">
            <input type="button" value="="  onClick="画面.print()">
        </div>
    `;
        画面 = { // ★
            i    : 0,
            add  : function(delta){this.i += delta;},
            print: function(){document.getElementById("カウンタ").innerHTML = this.i;}
        };
        画面.print();

        </script>
    </head>
    <body></body>
</html>

これをブラウザから表示すると、RefarenceErrorになる。
なぜならtype="module"の場合、varなどなしに変数を宣言できないからだ。

★の行をvar 画面 = {に代えると、最初こそ描画されるが、ボタンをクリックしたときに画面 not defined at HTMLInputElement.onclickと怒られる。
headタグ内でvarにて定義したローカル変数を、body以下の要素で利用しようとしたのだから当然だ。

ようするにtype="module"のスクリプト内で定義した変数を、同じファイル内の別の個所で利用しようとすると詰むのだ。
そもそもtype="module"は、グローバルスコープで動かない。

しかし抜け道がある。それこそがwindowオブジェクトの利用だ。

windowオブジェクトは、JavaScriptコードが動作しているWebブラウザのウィンドウまたはフレームを表すオブジェクトだ。
なので、ここにglobalsプロパティを勝手に追加し、window.globalsへグローバル変数とその値を記述した連想配列(=オブジェクト)を代入してしまえば、その内容は同じフレーム内のどこからでも取り出すことが出来るというわけだ。

ちなみに、参考2によれば、javascriptはそれがブラウザで実行されていようがNode.js上で実行されていようが、スクリプト実行前に一つ「Globalオブジェクト」と呼ばれるものを生成し、これは実行環境全体で共有されるそうだ。ブラウザで実行されるjavascriptにおいて、「Globalオブジェクト」とはwindowそのものである。

動作する例は次の通り。

type="module"でもグローバらせてくれるwindowさん(変更点は全5か所)
<html>
    <head>
        <script type="module">
        document.body = document.createElement("body");
        document.body.innerHTML = `
        <div id="カウンタ"></div>
        <div id="ボタンたち">
            <input type="button" value="++" onClick="window.globals.画面.add(1)"> // 変更点
            <input type="button" value="--" onClick="window.globals.画面.add(-1)">// 変更点
            <input type="button" value="="  onClick="window.globals.画面.print()">// 変更点
        </div>
    `;
        var 画面 = { // 変更点
            i    : 0,
            add  : function(delta){this.i += delta;},
            print: function(){document.getElementById("カウンタ").innerHTML = this.i;}
        };
        画面.print();
        window.globals = {画面:画面}; // 変更点
        </script>
    </head>
    <body></body>
</html>

See the Pen Untitled by 平田 智剛 (@17ec084) on CodePen.

参考

1.

2.

5
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0