Elsaの技術日記(徒然なるままに)

主に自分で作ったアプリとかの報告・日記を記載

MENU

javascriptをtype="module"で読み出すとonclickイベントで関数がis not definedになる

先日調査したjsonデータ⇔csvデータ変換やjsonデータ⇔xmlデータ変換や各種ファイルを出力する方法をまとめました。
elsammit-beginnerblg.hatenablog.com
elsammit-beginnerblg.hatenablog.com

どうせなのでこれらのコードをgithub pagesで公開したら後で便利かな?
と思い立ち、Webアプリを作成中!!

そこで、
ファイル分割のためにexport/importを使用したところ、
ちょっとハマったことがあるので備忘録としてまとめたいと思います。



■export/importを用いてファイル分割を行ってみる。

javascriptでは、export/importを用いることで、別ファイルで定義した関数を使用することが出来るようになります。

例えば、hoge1.jsとhoge2.jsを用意し、足し算を行う関数(add)をhoge2.jsで定義し、hoge1.jsで呼び出したいとします。
その場合には、こちらのように記載すればhoge1.jsでhoge2.jsで定義したadd関数をコール出来ます。
【hoge1.js】

import {add} from './hoge2.js'

const addhandler = () =>{
    alert(add(1,2));
}

【hoge2.js】

export function add(x,y){
    return x+y;
}

この際、htmlファイルではhoge1.jsを呼び出す必要があるのですが、
こちらのコードの通り、

<script src="hoge1.js" type="module"></script>

type="module"と定義する必要があります。

htmlファイルのコード。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script src="hoge1.js" type="module"></script>
        <title>Document</title>
    </head>
    <body>
        hello world
    </body>
</html>

■htmlでtype="module"でjavascriptファイルを読み出すとonclickイベントで関数がis not defined

先ほど記載しました通り、
export/importでファイル分割して別ファイルの関数を呼び出すことができる。
export/importを使用するためには、

<script src="hoge1.js" type="module"></script>

が必要。
となります。

ここで、hoge1.jsとhtmlファイルをこちらのように変更してみます。

import {add} from './hoge2.js'

const addhandler = () =>{
    alert(add(1,2));
}

const ClickFunc = () =>{
    alert('Hello World');
}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script src="hoge1.js" type="module"></script>
        <title>Document</title>
    </head>
    <body>
        hello world
        <button type="button" onClick="ClickFunc ()">Click!!(xml)</button>
    </body>
</html>

変更点ですが、
buttonタグを追加してボタンクリックした際に、
onClickイベントによりClickFunc ()がコールされるように追加した
のみになります。

ですが、こちらを実行してみると、、、
ClickFunc が
is not defined
と関数が定義されていない旨のエラーメッセージが表示されます。

■is not definedの原因

type="module"にしたことで”モジュールスコープ”になってしまったことで
is not definedと参照出来ない状況になっていたようです。

モジュールスコープになっていることにより、
モジュール内のすべての宣言は、モジュールにスコープされます。
他のjavasciptがこれらの宣言にアクセスしようとすると、参照エラーがスローされます。

これにより、
hoge1.jsで定義されたClickFunc はhoge1.js内でのみでしか使用できない状態のため、
onClickイベントにて関数が見つけられない(is not defined)になってしまった。
ということです。

■is not definedの解決方法

解決方法ですが、hoge1.jsで定義するClickFunc()に対して下記の通り、
明示的にwindowオブジェクトへ公開すればOKです。

import {add} from './hoge2.js'

const addhandler = () =>{
    alert(add(1,2));
}

window.ClickFunc = () =>{
    alert('Hello World');
}

もしくは、onClickは用いずに
addEventListenerハンドラーを用いればOKです。

■最後に

今回は自分がはまったtype="module"で、
onclickイベントで関数がis not definedになる現象に関して原因と解決方法をまとめました。

今回は、onclickイベントを例に記載しましたが
onloadやonChangeなどでhtmlから呼び出す関数に対して、
今回の解決方法を適用しないとis not definedになってしまいます。
注意しておかないとハマってしまいそうですね。。
気を付けて実装していきます。