Local Google Fonts

フォント設定

900

単なる自分のやらかしの共有です。この記事は事実をもとにしたフィクションです。

消し忘れたclose()関数

あるときモーダルコンポーネントを閉じる、close()関数というのを作りました。後日、リファクタリングをするときこの呼び出されているclose()関数がとあるコンポーネントから取り除かれることになりました。しかし誤って1つ削除し忘れてしまい、close()関数が取り残されてしまいます。

このとき、import文なども取り除かれたのですが、何故か未定義エラーなどは出ずに見過ごされてしまいました。(察しの良い人はピンとくるかも)

何故か消えるウィンドウ

そんな中、消し忘れたコンポーネントを含む画面で特定の手順を踏むと開いたブラウザウィンドウが閉じてしまう現象が確認されるようになりました。

どうやら発生源は先程のリファクタリング作業らしい…

window.closeというJavaScriptの組込み関数

この不具合の原因はJavaScriptのwindowオブジェクトに生えているclose()組込み関数です。windowオブジェクトは省略可能なため、close()単体でもwindow.close()関数が実行されます。

そのため先程の消し忘れた関数はそのまま組込み関数のclose()関数として解釈され、エラーにもならずブラウザウィンドウを閉じる[1]関数へと転生してしまったのです。

予防法

原因が分かれば不思議なことはないのですが、このような事故を防ぐ方法もあります。

1 単語の命名をやめる

ローテクな方法ですがcloseやopenのような1単語の命名をやめることです。事故予防だけでなく、コード品質の観点からも良い点があります。例えばcloseという関数名は何を閉じるのか明確ではありません。今回で言えばcloseModalという関数名ならバッティングも起こらず、関数の役割として明確でした。関数名は具体的動作を示す方がよいでしょう。

2 ESLintで縛る

こちらは機械的な手法で、ESLintのno-restricted-globalsというルールを使って縛るのも手です。

このルールは指定したグローバル変数の利用を制限します。今回の件なら"no-restricted-globals": ["error", "close"]と指定すればグローバル変数としてのclose()関数の利用を制限でき、反する場合はLintエラーとして検出されます。ほかにもopenやlocationといった変数も縛れます。

まとめ

命名は些細なようで大事です。命名によっては今回の事故のようになることもあり、全体のコード品質にも影響を与える可能性があります。1つ1つ丁寧な命名を心がけるとよりよい開発となっていくでしょう。

[1]window.close()関数はwindow.open()などによるスクリプトによって開かれたウィンドウのみ閉じます。そのためこの現象の発生には特定の手順を踏む必要があります。