見出し画像

JavaScript(ES2015~)における定数の書き方について考えてみた

こんにちは、AQUARING かに です。

JSを書くときに、不変な値を定数としてconstants.js(多いときはconstantsディレクトリのカテゴリごとのjsファイル)に書くのですが、この定数の持たせ方について考えてみました。

色の定数を例にとって説明していきます。

パターン1: 用途ごとにオブジェクトで構造化してconstで定義

const Color = {
  White: '#FFFFFF',
  Black: '#000000'
};

export { Color };

メリット
・ひとつ import するだけで中の値が全て使える(オブジェクトなので当たり前ですが)
・Object.prototypeの関数が使えるのでfor文で回したりいろいろできる

import { Color } from './constants.js';

for (const [key, value] of Object.entries(Color)) {
  console.log(key, value);// >> Whie #FFFFFF
                          // >> Black #000000
}

デメリット
・オブジェクトをexportするので、プロパティ単位ではTreeShakingが効かない(開発時の消し忘れなどで未使用のプロパティがあってもバンドルに含まれてしまう)

・オブジェクトそのものは代入不可になるが、オブジェクトのプロパティについてはその限りではない。(プロパティに再代入された場合に値が書き換わってしまう)

import { Color } from './constants.js';

console.log(Color.White);// >> #FFFFFF

Color.White = '#FF0000';
console.log(Color.White);// >> #FF0000

Color = { Red: '#FF0000' };// >> Uncaught TypeError: Assignment to constant variable.

ですが、Objectついて調べていたらObject.freeze()というプロパティを凍結(変更・追加・削除を禁止)させる関数があることが判明しました。

これでプロパティに再代入されちゃう問題は解決できます。

const Color = {
  White: '#FFFFFF',
  Black: '#000000'
};
Object.freeze(Color);// プロパティを凍結

export { Color };
import { Color } from './constants.js';

console.log(Color.White);// >> #FFFFFF

Color.White = '#FF0000';// >> Uncaught TypeError: Cannot assign to read only property 'White' of object '#<Object>'
console.log(Color.White);

パターン2:変数名の命名規則で構造化して値ひとつずつをconstで定義

const COLOR_WHITE = '#FFFFFF';
const COLOR_BLACK = '#000000';

export {
  COLOR_WHITE,
  COLOR_BLACK
};

three.js の constants もこの書き方になっています。(命名規則での構造化まではされていないですが)

メリット
・変数をひとつずつexportするので、TreeShakingが効く

デメリット
・いちいちimportしないといけない(importブロックの肥大化)
・あくまで命名規則上での構造化なので、まとめて配列として使いたい時に記述が増える

const COLOR_WHITE = '#FFFFFF';
const COLOR_BLACK = '#000000';

const COLOR_ARR = [
  COLOR_WHITE,
  COLOR_BLACK
];
 
export {
  COLOR_WHITE,
  COLOR_BLACK,
  COLOR_ARR
};

使ってみた感想

2パターンともプロジェクトで使ってみたのですが、どちらも一長一短なのでいまだに最適な書き方がわからずです、、みなさんどういう感じで定数書いてるんでしょう?

このへんあんまりこだわってると「TypeScript使えば?」って言われそうですが、EcmaScriptはそのままブラウザで動くのがいいんですよね、、

この記事が気に入ったらサポートをしてみませんか?