業務・実務で使える JavaScript ユーティリティ:文字列を CONSTANT_CASE に変換する方法
JavaScriptで文字列を CONSTANT_CASE に変換する処理は、業務開発でとてもよく使います。たとえば、設定キー、環境変数名、定数名、CSVヘッダーの正規化、外部データのキー統一などで役立ちます。
CONSTANT_CASE とは、単語をアンダースコアでつなぎ、全体を大文字にした形式です。たとえば userName を USER_NAME に、api endpoint url を API_ENDPOINT_URL に変換したものです。
一見すると単純そうに見えますが、実務では空白、ハイフン、camelCase、PascalCase、連続記号、日本語、null や undefined など、さまざまな入力を考慮する必要があります。そのため、ただ大文字にするだけでは足りません。入力の揺れをどこまで吸収するかを最初に決め、その仕様に沿って処理を組み立てることが大切です。
まず押さえたい:CONSTANT_CASE とは何か
CONSTANT_CASE は、主に「変更されない値」や「共通ルールで管理したい識別子」を扱う場面で使われます。JavaScriptそのものが定数名にこの形式を強制するわけではありませんが、実務では広く使われる命名スタイルです。
- 定数名:
MAX_RETRY_COUNT - 環境変数:
DATABASE_URL - 設定キーの統一:
DEFAULT_THEME_COLOR - 外部入力の正規化:
USER_ID、ORDER_STATUS
この形式を使うメリットは、単語の区切りが見やすく、定数であることがひと目でわかりやすいことです。また、データのキー名に統一ルールがあると、保守やレビューもしやすくなります。
最初に決めるべきこと:入力と出力の仕様
初心者のうちほど重要なのが、いきなりコードを書かずに「どんな入力を、どういう出力にするか」を先に決めることです。ここを曖昧にすると、あとで例外処理がどんどん増え、コードが読みにくくなります。
たとえば、次のような入力をどう扱うかを事前に決めます。
"user name"→USER_NAME"user-name"→USER_NAME"userName"→USER_NAME"UserName"→USER_NAME" user name "→USER_NAME"user__name"→USER_NAMEにするのか、そのままにするのかnullやundefinedは空文字にするのか、エラーにするのか- 日本語
"ユーザー名"を許可するのか
実務では、この「仕様決め」が品質に直結します。関数を書く前に、少なくとも代表的な入力例を5個から10個ほど並べる習慣をつけると、かなり堅い実装になります。
ステップバイステップで考える
ここからは、文字列を CONSTANT_CASE に変換する流れを、できるだけわかりやすく順番に見ていきます。
ステップ1:前後の余分な空白を取り除く
ユーザー入力やCSVデータ、フォーム値には、前後に不要な空白が入っていることがよくあります。このまま処理すると、意図しないアンダースコアが付いたり、比較処理でズレたりします。
そこで最初に trim() を使って、前後の空白を削除します。
// 前後の空白を取り除く例
const input = " user name ";
const trimmed = input.trim();
console.log(trimmed); // "user name"JavaScriptこの一手間は地味ですが、とても重要です。実務では「とりあえず最初に整える」前処理が、後ろの処理をかなり簡単にしてくれます。
ステップ2:単語の区切りをそろえる
CONSTANT_CASE では単語の区切りをアンダースコアに統一します。しかし入力は、空白区切りだったり、ハイフン区切りだったり、複数スペースだったりします。
そのため、まずは「区切りになりそうなもの」をアンダースコアにそろえる発想が必要です。
// 空白やハイフンをアンダースコアに統一する例
const input = "user-name test";
const normalized = input.replace(/[\s-]+/g, "_");
console.log(normalized); // "user_name_test"JavaScriptここで使っている正規表現 /[\s-]+/g は、次の意味です。
\sは空白文字を表します-はハイフンを表します[...]は「この中のどれか1文字」を表します+は「1回以上の繰り返し」ですgは「見つかったすべてを置換する」です
つまり、空白やハイフンが1文字でも複数でも続いていたら、まとめて _ に置き換える、という意味です。
ステップ3:camelCase や PascalCase の区切りを見つける
実務では userName や UserName のような形式もよく入力されます。これらは空白もハイフンもないので、ステップ2だけでは USERNAME になってしまい、単語の区切りが失われます。
そこで「小文字または数字の直後に大文字が来たら、そこが単語の切れ目だ」と判断して、間にアンダースコアを入れます。
// camelCase や PascalCase の区切りにアンダースコアを入れる例
const input = "userName";
const separated = input.replace(/([a-z0-9])([A-Z])/g, "\$1_\$2");
console.log(separated); // "user_Name"JavaScriptこの正規表現 /([a-z0-9])([A-Z])/g は、次のように読めます。
([a-z0-9])は小文字または数字を1文字つかまえます([A-Z])はその直後の大文字を1文字つかまえます$1_$2は「前半 + アンダースコア + 後半」に置き換える意味です
たとえば userName は rN の部分がマッチし、user_Name になります。
この処理はとても重要です。なぜなら、業務データには人が手で入力した文字列だけでなく、別システム由来のキー名やAPIのレスポンス名が混ざるからです。区切り方が統一されていないデータをどう吸収するかが、ユーティリティ関数の価値になります。
ステップ4:最後に大文字へ変換する
区切りを整えたら、最後に全体を大文字へ変換します。ここで toUpperCase() を使います。
// 全体を大文字に変換する例
const input = "user_name";
const upper = input.toUpperCase();
console.log(upper); // "USER_NAME"JavaScriptこの順番も大切です。先に大文字化してしまうと、camelCase の境目を見つけにくくなる場合があります。そのため、一般には「区切りを整えてから大文字化する」ほうが扱いやすいです。
まずは基本版を作る
ここまでの考え方をまとめると、基本版の関数は次のようになります。
// 文字列を CONSTANT_CASE に変換する基本版
function toConstantCase(str) {
return str
// 1. 前後の空白を削除する
.trim()
// 2. camelCase / PascalCase の区切りにアンダースコアを入れる
.replace(/([a-z0-9])([A-Z])/g, "\$1_$2")
// 3. 空白やハイフンをアンダースコアに統一する
.replace(/[\s-]+/g, "_")
// 4. 全体を大文字に変換する
.toUpperCase();
}
// 動作確認
console.log(toConstantCase("userName")); // "USER_NAME"
console.log(toConstantCase("UserName")); // "USER_NAME"
console.log(toConstantCase("user name")); // "USER_NAME"
console.log(toConstantCase("user-name")); // "USER_NAME"
console.log(toConstantCase(" api endpoint ")); // "API_ENDPOINT"JavaScriptこの基本版でもかなり実用的です。ただし、実務ではこれだけだとまだ不十分なことがあります。
実務で重要になる注意点
null や undefined をどう扱うか
実務コードでは、必ずしも入力がきれいな文字列とは限りません。フォーム値、APIレスポンス、CSV解析結果、設定ファイルなどから値が来ると、null や undefined が混ざることがあります。
この状態でいきなり trim() を呼ぶとエラーになります。
// これはエラーになる例
const value = null;
value.trim(); // TypeErrorJavaScriptそのため、防御的に書くなら、最初に文字列化するか、文字列以外を弾く必要があります。
// null や undefined を安全に扱う例
function toConstantCaseSafe(str) {
// null または undefined の場合は空文字を返す
if (str == null) {
return "";
}
return String(str)
.trim()
.replace(/([a-z0-9])([A-Z])/g, "\$1_$2")
.replace(/[\s-]+/g, "_")
.toUpperCase();
}JavaScriptstr == null は、null と undefined の両方をまとめて判定したいときによく使われます。初心者のうちは「なぜ === null ではないのか」と感じるかもしれませんが、この用途では便利な書き方です。
連続アンダースコアの整理
入力によっては、すでにアンダースコアが入っていたり、空白とハイフンが混ざっていたりして、結果としてアンダースコアが連続することがあります。
たとえば次のようなケースです。
"user__name""user - name"" user --- name "
これをそのままにすると、見た目や統一性が崩れます。そのため、連続するアンダースコアを1個にまとめる処理を入れることが多いです。
// 連続するアンダースコアを1個にまとめる例
const input = "user___name";
const normalized = input.replace(/_+/g, "_");
console.log(normalized); // "user_name"JavaScript先頭と末尾のアンダースコアを除去する
置換の過程によっては、先頭や末尾にアンダースコアが残る場合があります。たとえば、記号を区切りとしてまとめて処理したときなどです。
こうした余分なアンダースコアは、最終的に取り除くと見た目が整います。
// 先頭と末尾のアンダースコアを削除する例
const input = "_user_name_";
const cleaned = input.replace(/^_+|_+$/g, "");
console.log(cleaned); // "user_name"JavaScript^ は文字列の先頭、$ は文字列の末尾を表します。つまりこの正規表現は、「先頭の連続アンダースコア」または「末尾の連続アンダースコア」を削除しています。
英数字以外をどう扱うか
ここは実務で特に重要です。なぜなら、どこまで許可するかで仕様が大きく変わるからです。
たとえば、記号をどうするかを決める必要があります。
"user.name"をUSER_NAMEにするのか"price(税込)"をどう扱うのか"error#code"をERROR_CODEにするのか
業務用途では、英数字以外は区切りとみなしてアンダースコアに寄せるほうが扱いやすいことが多いです。ただし、用途によっては日本語や一部記号を残したいこともあります。
このため、「何を残して、何を落とすか」は先に決める必要があります。ユーティリティ関数は便利ですが、曖昧なまま万能にしようとすると、逆に使いにくくなります。
日本語を含む場合の考え方
日本語を含む文字列を CONSTANT_CASE にしたいケースもあります。ただし、英語圏の命名規則を前提にした処理なので、日本語に対しては期待どおりに「単語境界」を判定しにくいです。
たとえば "ユーザー 名" なら空白で区切れますが、"ユーザー名" のように連続した日本語から自然な単語分割をするのは、通常の簡単な正規表現では困難です。
そのため、日本語を含む入力では次のどちらかに寄せるのが現実的です。
- 日本語はそのまま残し、区切りだけ整える
- 英数字ベースの識別子のみを対象にし、日本語入力は別ルールにする
実務では後者のほうが安全です。識別子や設定キーに使うなら、入力段階で英数字に制限する設計のほうがトラブルを減らせます。
実務向けの完成版テンプレート
ここまでの注意点を踏まえて、実務で比較的使いやすいテンプレートを示します。これは「できるだけ入力の揺れを吸収して、きれいな CONSTANT_CASE を返す」ことを目的にした例です。
// 文字列を実務向けに CONSTANT_CASE へ変換する関数
function toConstantCase(value) {
// null または undefined は空文字として扱う
if (value == null) {
return "";
}
return String(value)
// 1. 前後の空白を削除する
.trim()
// 2. camelCase / PascalCase の境目にアンダースコアを入れる
.replace(/([a-z0-9])([A-Z])/g, "\$1_\$2")
// 3. 英数字以外の連続をアンダースコアに置き換える
// 空白、ハイフン、記号などをまとめて区切りとして扱う
.replace(/[^a-zA-Z0-9]+/g, "_")
// 4. 連続するアンダースコアを1個にまとめる
.replace(/_+/g, "_")
// 5. 先頭と末尾のアンダースコアを削除する
.replace(/^_+|_+$/g, "")
// 6. 最後に大文字へ変換する
.toUpperCase();
}
// 動作確認用の例
console.log(toConstantCase("userName")); // "USER_NAME"
console.log(toConstantCase("UserName")); // "USER_NAME"
console.log(toConstantCase("user name")); // "USER_NAME"
console.log(toConstantCase("user-name")); // "USER_NAME"
console.log(toConstantCase(" user---name ")); // "USER_NAME"
console.log(toConstantCase("api.endpoint url")); // "API_ENDPOINT_URL"
console.log(toConstantCase("error#code")); // "ERROR_CODE"
console.log(toConstantCase("__already__ok__")); // "ALREADY_OK"
console.log(toConstantCase(null)); // ""
console.log(toConstantCase(undefined)); // ""
console.log(toConstantCase(12345)); // "12345"JavaScriptこのテンプレートの重要ポイントは、「正規化の順番」が整理されていることです。実務では1個1個の正規表現よりも、処理の順番のほうが品質に効きます。
- 最初に前後のノイズを落とす
- 次に単語境界を補う
- その後に区切り記号を統一する
- 最後に見た目を整える
この順番で考えると、コードの意図が読みやすくなり、あとで保守しやすくなります。
処理の流れを具体例で追う
たとえば入力が " userName-test value " だったとします。この文字列がどのように変換されるかを順番に見てみます。
変換の途中経過
- 元の文字列:
" userName-test value " trim()後:"userName-test value"- camelCase区切り追加後:
"user_Name-test value" - 記号・空白をアンダースコア化後:
"user_Name_test_value" - 大文字化後:
"USER_NAME_TEST_VALUE"
このように、いきなり完成形を作るのではなく、「文字列を少しずつ整形していく」と考えると理解しやすくなります。
例題で理解を固める
例題1:基本的な変換
次の入力を CONSTANT_CASE に変換してみます。
// 例題1
console.log(toConstantCase("first name")); // "FIRST_NAME"
JavaScript空白区切りをアンダースコアに変え、最後に大文字化しています。もっとも基本的なパターンです。
例題2:camelCase の変換
// 例題2
console.log(toConstantCase("firstName")); // "FIRST_NAME"
JavaScriptここでは tN の位置を単語の境目として検出できるかがポイントです。単に大文字にするだけでは FIRSTNAME になってしまうため、境界の補完が必要です。
例題3:記号が混ざるケース
// 例題3
console.log(toConstantCase("user.id#main")); // "USER_ID_MAIN"
JavaScript実務では、ドットやシャープなどが混ざる入力は珍しくありません。こうした記号を「区切り」としてまとめて処理できると、かなり便利です。
例題4:すでに近い形の文字列
// 例題4
console.log(toConstantCase("USER_NAME")); // "USER_NAME"
JavaScriptすでに理想形に近い入力が来ても、大きく壊さずにそのまま返せるのがよいユーティリティ関数です。こういう性質を「冪等的に近い」と考えるとよいです。つまり、何度通しても大きく崩れないことが大切です。
テストをまとめて確認する方法
関数は「たまたま1件動いた」だけでは不十分です。実務では、複数のパターンをまとめて確認する習慣がとても重要です。
// 代表的な入力と期待値をまとめてテストする例
const testCases = [
["userName", "USER_NAME"],
["UserName", "USER_NAME"],
["user name", "USER_NAME"],
["user-name", "USER_NAME"],
[" user---name ", "USER_NAME"],
["api.endpoint url", "API_ENDPOINT_URL"],
["error#code", "ERROR_CODE"],
["__already__ok__", "ALREADY_OK"],
[null, ""],
[undefined, ""],
[12345, "12345"]
];
for (const [input, expected] of testCases) {
const actual = toConstantCase(input);
// 結果を比較して表示する
console.log({
input,
expected,
actual,
pass: actual === expected
});
}JavaScriptこのように「入力」「期待値」「実際の結果」をセットで確認すると、仕様漏れやバグに気づきやすくなります。初心者の段階から、コードを書くことと同じくらいテストケースを並べることを大事にすると、成長が速くなります。
実務での活用例
環境変数名の生成
設定項目名から環境変数名を作る場面はよくあります。
// 設定キーから環境変数名を作る例
const settingKey = "databaseUrl";
const envName = toConstantCase(settingKey);
console.log(envName); // "DATABASE_URL"JavaScriptCSVヘッダーの正規化
CSVファイルの列名は、人によって書き方がバラバラになりがちです。そのため、読み込み時に正規化しておくと、後続処理が安定します。
// CSVヘッダーを正規化する例
const headers = ["First Name", "last-name", "EmailAddress"];
const normalizedHeaders = headers.map(toConstantCase);
console.log(normalizedHeaders);
// ["FIRST_NAME", "LAST_NAME", "EMAIL_ADDRESS"]JavaScriptオブジェクトキーの統一
外部APIや複数の入力元からデータを集める場合、キーの形式が統一されていないことがあります。そんなときに変換関数を使うと、扱いやすくなります。
// オブジェクトのキーを CONSTANT_CASE に統一する例
function normalizeObjectKeys(obj) {
const result = {};
for (const key in obj) {
// 元のキーを CONSTANT_CASE に変換して代入する
result[toConstantCase(key)] = obj[key];
}
return result;
}
const input = {
firstName: "Taro",
"last-name": "Yamada",
"email address": "[email protected]"
};
console.log(normalizeObjectKeys(input));
/*
{
FIRST_NAME: "Taro",
LAST_NAME: "Yamada",
EMAIL_ADDRESS: "[email protected]"
}
*/JavaScript初心者がつまずきやすいポイント
正規表現だけを見て理解しようとしてしまう
初心者の方は、正規表現の記号だけを細かく追って混乱しがちです。しかし大事なのは、先に「何をしたいか」を言葉で整理することです。
- 前後の空白を消したい
- 単語の区切りをそろえたい
- camelCase の境目を見つけたい
- 最後に大文字へ変えたい
この日本語の設計図が先にあれば、正規表現はそれを実現する部品として理解しやすくなります。
一発で完璧な変換を目指してしまう
実務では、最初から万能な関数を作る必要はありません。むしろ、対象となるデータの実態に合わせて少しずつ育てるほうが安全です。
たとえば、最初は次の範囲だけ対応すれば十分かもしれません。
- 空白
- ハイフン
- camelCase
その後、必要に応じて記号や日本語対応を足していけばよいです。最初から全部やろうとすると、かえって仕様がぶれやすくなります。
入力データを信用してしまう
実務で特に大切なのはここです。外から入ってくる値は、きれいだと思わないことです。余分な空白、想定外の記号、数値、null、空文字など、何でも来る前提で考えるとコードが強くなります。
これは情報セキュリティや堅牢性の観点でも重要です。文字列変換そのものは小さな処理でも、入力を無条件に信用する癖がつくと、別の場面で脆さにつながります。ユーティリティ関数こそ、防御的に書く習慣を身につける練習に向いています。
より実務的に考えるための判断基準
CONSTANT_CASE 変換は、単なる見た目の整形ではありません。業務では「どの文字を同一視するか」「何を不正入力とみなすか」を決める設計作業でもあります。
そのため、実装前に次の観点を確認するのがおすすめです。
- 入力は必ず文字列なのか
- 数値を受け取る可能性はあるのか
- 日本語や記号を許可するのか
- 空文字を許すのか
- 不正値は空文字にするのか、例外にするのか
- 既存データとの互換性は必要か
この確認をしておくと、「変換できれば正しい」ではなく「業務要件に合っているから正しい」という判断ができるようになります。
すぐ使える最終テンプレート
最後に、業務で流用しやすい形でテンプレートをまとめます。
/**
* 値を CONSTANT_CASE に変換する
*
* 仕様:
* - null / undefined は空文字を返す
* - camelCase / PascalCase に対応する
* - 空白、ハイフン、各種記号はアンダースコアとして扱う
* - 連続アンダースコアは1つにまとめる
* - 先頭末尾のアンダースコアは削除する
* - 最後に大文字へ変換する
*/
function toConstantCase(value) {
// null / undefined は空文字にする
if (value == null) {
return "";
}
return String(value)
// 前後の空白を削除する
.trim()
// camelCase / PascalCase の区切りを補う
.replace(/([a-z0-9])([A-Z])/g, "\$1_\$2")
// 英数字以外を区切りとしてアンダースコア化する
.replace(/[^a-zA-Z0-9]+/g, "_")
// 連続するアンダースコアを1つにまとめる
.replace(/_+/g, "_")
// 先頭と末尾のアンダースコアを削除する
.replace(/^_+|_+$/g, "")
// 全体を大文字へ変換する
.toUpperCase();
}
// 使用例
console.log(toConstantCase("userName")); // "USER_NAME"
console.log(toConstantCase("API endpoint url")); // "API_ENDPOINT_URL"
console.log(toConstantCase(" error-code#main ")); // "ERROR_CODE_MAIN"
console.log(toConstantCase(null)); // ""JavaScriptまとめ
JavaScriptで文字列を CONSTANT_CASE に変換する処理は、見た目以上に実務的な価値があります。単に大文字とアンダースコアへ変えるだけではなく、入力の揺れをどこまで吸収するかを設計することが重要です。
特に大切なのは次の点です。
- 最初に入力と出力の仕様を決めること
- 前処理、区切り補完、記号統一、大文字化の順で考えること
nullや記号混在など、実務で起きる入力の乱れを想定すること- 代表的なテストケースを最初から用意すること
初心者のうちは、正規表現そのものよりも「文字列を段階的に整えていく」という考え方を身につけることが重要です。この考え方は snake_case、kebab-case、入力正規化、検索用前処理などにもそのまま応用できます。
つまり、今回のテーマは単なる小技ではなく、実務で通用する文字列処理の基礎そのものです。小さなユーティリティ関数でも、仕様を明確にし、防御的に書き、テストで確かめる。この姿勢が、読みやすく壊れにくいコードにつながります。

