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

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


# そもそもの問題

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

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

```html: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`そのものである。


動作する例は次の通り。

```html: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>
```

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="Vwymjzb" data-user="17ec084" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/17ec084/pen/Vwymjzb">
  Untitled</a> by 平田 智剛 (<a href="https://codepen.io/17ec084">@17ec084</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


# 参考
## 1. 
http://var.blog.jp/archives/77519253.html

## 2.
https://javascript.keicode.com/lang/global-object.php