何をしたいユーティリティか:「拡張子取得」
ここで作りたいのは、URL やパス文字列から「拡張子(.png や .js など)」だけを取り出す小さな関数です。
https://example.com/assets/logo.png → "png"/scripts/app.min.js → "js"/download/file → ""(拡張子なし)
こういう判定ができると、例えば次のようなことが簡単になります。
画像かどうかで処理を分ける。
ダウンロード時のアイコンを切り替える。
アップロードされたファイルの種類をざっくりチェックする。
そのための「拡張子取得ユーティリティ」を、URL を前提にかみ砕いて作っていきます。
拡張子取得の基本的な考え方
どこからどこまでを「拡張子」とみなすか
拡張子取得でやりたいことは、ざっくり言うとこうです。
- URL から「最後のパス部分」だけを取り出す(ファイル名っぽいところ)。
- その中で「最後のドット以降」を拡張子とみなす。
- ドットがなければ「拡張子なし」と判断する。
例えば、https://example.com/assets/logo.png なら、
URL 全体 → https://example.com/assets/logo.png
最後の / 以降 → logo.png
最後の . 以降 → png
という流れです。
逆に、/download/file のように . がなければ、拡張子はないと判断します。
一番シンプルな「拡張子取得」関数
URL 文字列から拡張子を取る getExtension
まずは、クエリやハッシュを無視して、「パス部分だけから拡張子を取る」関数を作ります。
function getExtension(url) {
if (!url) return "";
const str = String(url);
const pathWithoutQuery = str.split(/[?#]/)[0];
const lastSlashIndex = pathWithoutQuery.lastIndexOf("/");
const filename =
lastSlashIndex >= 0
? pathWithoutQuery.slice(lastSlashIndex + 1)
: pathWithoutQuery;
if (!filename) return "";
const lastDotIndex = filename.lastIndexOf(".");
if (lastDotIndex <= 0) {
return "";
}
return filename.slice(lastDotIndex + 1).toLowerCase();
}
JavaScript重要なポイントをかみ砕いて説明する
ここがこのユーティリティの心臓部なので、丁寧に見ていきます。
1. クエリやハッシュは先に切り落とす
const pathWithoutQuery = str.split(/[?#]/)[0];
JavaScriptURL には、? 以降のクエリや # 以降のハッシュが付いていることがあります。
/assets/logo.png?version=1#top
拡張子を取りたいのは「パス部分」だけなので、? または # で分割して、
一番前の部分だけを使います。
結果として、/assets/logo.png だけが残ります。
2. 最後の / 以降を「ファイル名」とみなす
const lastSlashIndex = pathWithoutQuery.lastIndexOf("/");
const filename =
lastSlashIndex >= 0
? pathWithoutQuery.slice(lastSlashIndex + 1)
: pathWithoutQuery;
JavaScript/assets/logo.png のようなパスから、最後の / 以降を取り出します。
lastIndexOf("/") は「一番後ろの / の位置」を返します。
そこから +1 した位置から最後までを slice すると、logo.png になります。
もし / が含まれていない場合(単なる "logo.png" など)は、そのまま全体をファイル名とみなします。
3. ドットがなければ拡張子なし
if (!filename) return "";
const lastDotIndex = filename.lastIndexOf(".");
if (lastDotIndex <= 0) {
return "";
}
JavaScriptlastIndexOf(".") で「一番後ろの .」を探します。
<= 0 のときは拡張子なしと判断しています。
理由はこうです。
"file" → lastIndexOf(".") === -1 → ドットなし → 拡張子なし。".gitignore" → lastIndexOf(".") === 0 → 先頭のドット → 「隠しファイル名」とみなして拡張子なし。
.gitignore のような「先頭ドットのファイル」は、拡張子ではなく「ファイル名の一部」と考えるのが一般的なので、ここでは拡張子なし扱いにしています。
4. 最後のドット以降を小文字で返す
return filename.slice(lastDotIndex + 1).toLowerCase();
JavaScript"logo.png" → lastDotIndex は "logo" の後ろ → slice(lastDotIndex + 1) で "png"。"PHOTO.JPG" → "JPG" を取り出して toLowerCase() で "jpg" に揃える。
拡張子は大文字・小文字が混ざることがあるので、
内部的には小文字に揃えて扱うのが実務では扱いやすいです。
実際の動きを例で確認する
典型的な URL の例
getExtension("https://example.com/assets/logo.png");
// "png"
getExtension("/scripts/app.min.js");
// "js"
getExtension("/images/photo.JPG");
// "jpg"
getExtension("/download/file");
// ""
JavaScript最後の /download/file は . がないので、拡張子なしとして空文字が返ってきます。
クエリやハッシュ付きの例
getExtension("/assets/logo.png?version=1");
// "png"
getExtension("/assets/logo.png#top");
// "png"
getExtension("/assets/logo.png?version=1#top");
// "png"
JavaScriptクエリやハッシュは先に切り落としているので、
拡張子取得には影響しません。
隠しファイルっぽい名前の例
getExtension("/config/.env");
// ""(拡張子なし扱い)
getExtension(".gitignore");
// ""(拡張子なし扱い)
JavaScript先頭のドットは「拡張子」ではなく「ファイル名の一部」とみなしているため、
ここでは拡張子なしとして扱っています。
実務での使いどころと設計のポイント
「拡張子でざっくり分類する」用途に向いている
このユーティリティは、「拡張子ベースでざっくり分類したい」ときにとても便利です。
例えば、こんなコードが書けます。
const ext = getExtension(url);
if (["png", "jpg", "jpeg", "gif", "webp"].includes(ext)) {
// 画像として扱う
} else if (["mp4", "webm"].includes(ext)) {
// 動画として扱う
} else {
// その他
}
JavaScriptアップロードされたファイルの種類をざっくりチェックしたり、
アイコンを切り替えたりするときに、拡張子取得はよく使われます。
「MIME タイプ判定」とは別物だと意識する
ここで作っているのは、あくまで「文字列としての拡張子」を取るだけのユーティリティです。
本当に安全にファイル種別を判定したい場合は、
サーバー側で MIME タイプを見たり、ファイルの中身をチェックしたりする必要があります。
フロント側の拡張子取得は、
- 表示用のアイコンを決める
- 軽いバリデーションをする
といった「ざっくり用途」に使う、という意識を持っておくと健全です。
ちょっとだけ手を動かしてみる
コンソールで、次のあたりを試してみてください。
getExtension("https://example.com/assets/logo.png");
getExtension("/scripts/app.min.js");
getExtension("/images/photo.JPG?size=large");
getExtension("/download/file");
getExtension("/config/.env");
JavaScript「どのケースで何が返ってくるか」を、自分の目で確認してみてください。
そのうえで、自分のプロジェクトに
export function getExtension(url) { ... }
JavaScriptを置いて、
URL やパスから拡張子が欲しくなったら、
毎回 split(".") ではなく、必ず getExtension を通す、というルールにしてみてください。
それだけで、あなたの「拡張子判定」は、
場当たり的な文字列操作から、意図がはっきりした“業務レベルの拡張子取得ユーティリティ”に一段レベルアップします。
