JavaScript URLエンコードの基本 - encodeURIComponentの使い方

JavaScriptのencodeURIComponentを使ったURLエンコードの方法を初心者向けに解説。特殊文字の処理から実用的なサンプルコードまで、わかりやすく説明します。

Learning Next 運営
26 分で読めます

JavaScript URLエンコードの基本 - encodeURIComponentの使い方

みなさん、WebアプリケーションでURLを扱っていて「日本語が文字化けした」ことありませんか?

「検索キーワードをURLパラメータで送信したい」 「ファイル名に日本語が含まれているリンクを作りたい」 「特殊文字がURLで正しく表示されない」

こんな場面に遭遇することってありますよね。

実は、これらの問題はencodeURIComponentを使ったURLエンコードで解決できるんです。 URLには使用できる文字に制限があるため、適切な変換処理が必要になります。

この記事では、JavaScriptのencodeURIComponentを使ったURLエンコードの方法について、基本的な使い方から実用的なサンプルコードまで詳しく解説します。 安全なURL処理ができるようになりますよ。

URLエンコードって何?

簡単に言うとどんなもの?

URLエンコードとは、URLで使用できない文字や特殊文字を、URLで安全に使用できる形式に変換することです。

URLには使用できる文字に制限があります。 日本語やスペース、記号などの文字はそのままでは正しく処理されません。

// エンコード前(問題のある例)
const badUrl = "https://example.com/search?q=Hello World&category=カテゴリ";
// エンコード後(正しい例)
const goodUrl = "https://example.com/search?q=Hello%20World&category=%E3%82%AB%E3%83%86%E3%82%B4%E3%83%AA";

上の例では、スペースが%20に、日本語が%E3%82%AB...のような形に変換されています。 これがURLエンコードの仕組みです。

encodeURIComponentの基本的な使い方

基本的な文法

const encodedString = encodeURIComponent(string);

とってもシンプルですね!文字列を渡すだけで、エンコードされた文字列が返ってきます。

具体的な使用例

// 日本語文字列のエンコード
const japaneseText = "こんにちは世界";
const encoded = encodeURIComponent(japaneseText);
console.log(encoded);
// 出力: %E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF%E4%B8%96%E7%95%8C
// スペースのエンコード
const textWithSpace = "Hello World";
const encodedSpace = encodeURIComponent(textWithSpace);
console.log(encodedSpace);
// 出力: Hello%20World
// 特殊文字のエンコード
const specialChars = "user@example.com";
const encodedSpecial = encodeURIComponent(specialChars);
console.log(encodedSpecial);
// 出力: user%40example.com

日本語は複雑な文字列に見えますが、これで正しくエンコードされています。 スペースは%20、@マークは%40に変換されますね。

デコードする方法

エンコードしたものを元に戻すこともできます。

// エンコードされた文字列をデコード
const encoded = "%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF";
const decoded = decodeURIComponent(encoded);
console.log(decoded);
// 出力: こんにちは

decodeURIComponentを使えば、エンコードされた文字列を元の形に戻せます。

エンコードが必要な文字

よくエンコードされる文字

どんな文字がエンコードされるのか見てみましょう。

const characters = {
space: " ",
japanese: "あいうえお",
email: "@",
ampersand: "&",
question: "?",
equals: "=",
hash: "#",
percent: "%",
plus: "+",
slash: "/",
backslash: "\\",
quote: '"',
singleQuote: "'",
brackets: "[]",
braces: "{}"
};
console.log("エンコード例:");
for (const [name, char] of Object.entries(characters)) {
console.log(`${name}: "${char}" → "${encodeURIComponent(char)}"`);
}

このコードを実行すると、それぞれの文字がどのようにエンコードされるかが分かります。

エンコードされない文字

一方で、エンコードされない安全な文字もあります。

// エンコードされない安全な文字
const safeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~";
console.log("安全な文字:", encodeURIComponent(safeChars));
// 出力: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~

アルファベット、数字、一部の記号はエンコードされません。

実用的なサンプルコード

検索URL生成

実際のWebアプリケーションでよく使われるパターンです。

function createSearchUrl(baseUrl, query, filters = {}) {
// クエリパラメータをエンコード
const encodedQuery = encodeURIComponent(query);
// フィルターパラメータもエンコード
const filterParams = Object.entries(filters)
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join('&');
let url = `${baseUrl}?q=${encodedQuery}`;
if (filterParams) {
url += `&${filterParams}`;
}
return url;
}
// 使用例
const searchUrl = createSearchUrl(
'https://example.com/search',
'JavaScript 入門',
{
category: 'プログラミング',
level: '初心者',
author: 'user@example.com'
}
);
console.log(searchUrl);

この関数は、検索キーワードとフィルター条件を受け取って、適切にエンコードされたURLを生成します。

フォームデータの送信

フォームからデータを送信するときにもエンコードが必要です。

function createFormData(data) {
const formParams = [];
for (const [key, value] of Object.entries(data)) {
if (value !== null && value !== undefined) {
const encodedKey = encodeURIComponent(key);
const encodedValue = encodeURIComponent(value.toString());
formParams.push(`${encodedKey}=${encodedValue}`);
}
}
return formParams.join('&');
}
async function submitForm(url, formData) {
const encodedData = createFormData(formData);
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: encodedData
});
return await response.json();
} catch (error) {
console.error('フォーム送信エラー:', error);
throw error;
}
}

使用例も見てみましょう。

// 使用例
const formData = {
name: '田中 太郎',
email: 'tanaka@example.com',
message: 'お問い合わせ内容です。よろしくお願いします!',
category: 'サポート'
};
submitForm('https://api.example.com/contact', formData);

フォームデータが適切にエンコードされて送信されます。

ファイルダウンロードリンクの生成

ファイル名に日本語が含まれる場合のダウンロードリンク生成例です。

function createDownloadLink(filename, data, mimeType = 'text/plain') {
// ファイル名をエンコード
const encodedFilename = encodeURIComponent(filename);
// データをBlob形式に変換
const blob = new Blob([data], { type: mimeType });
const url = URL.createObjectURL(blob);
// ダウンロードリンクを作成
const link = document.createElement('a');
link.href = url;
link.download = filename; // 実際のファイル名(エンコードしない)
link.textContent = `${filename} をダウンロード`;
return link;
}
function addDownloadButton(containerId, filename, data) {
const container = document.getElementById(containerId);
const link = createDownloadLink(filename, data);
container.appendChild(link);
// 使用後にURLを削除
link.addEventListener('click', () => {
setTimeout(() => {
URL.revokeObjectURL(link.href);
}, 1000);
});
}
// 使用例
const csvData = "名前,年齢,職業
田中太郎,30,エンジニア
佐藤花子,25,デザイナー";
addDownloadButton('download-container', 'ユーザーリスト.csv', csvData);

このコードは、日本語ファイル名のダウンロードリンクを安全に作成します。

動的URLの生成

URLを動的に組み立てるためのクラスです。

class UrlBuilder {
constructor(baseUrl) {
this.baseUrl = baseUrl;
this.params = new Map();
}
addParam(key, value) {
if (value !== null && value !== undefined) {
this.params.set(key, value);
}
return this;
}
addParams(paramsObject) {
for (const [key, value] of Object.entries(paramsObject)) {
this.addParam(key, value);
}
return this;
}
removeParam(key) {
this.params.delete(key);
return this;
}
build() {
if (this.params.size === 0) {
return this.baseUrl;
}
const queryString = Array.from(this.params.entries())
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join('&');
return `${this.baseUrl}?${queryString}`;
}
clone() {
const builder = new UrlBuilder(this.baseUrl);
builder.params = new Map(this.params);
return builder;
}
}

使用例も見てみましょう。

// 使用例
const apiUrl = new UrlBuilder('https://api.example.com/users')
.addParam('page', 1)
.addParam('limit', 20)
.addParam('search', 'プログラマー')
.addParam('sort', 'created_at:desc')
.build();
console.log(apiUrl);

メソッドチェーンで簡単にパラメータを追加できる便利なクラスです。

encodeURIとencodeURIComponentの違い

基本的な違い

似たような名前のメソッドがあるので、違いを理解しましょう。

const url = "https://example.com/path?name=田中太郎&email=user@example.com";
// encodeURI - URL全体をエンコード(URLの構造は保持)
console.log(encodeURI(url));
// https://example.com/path?name=%E7%94%B0%E4%B8%AD%E5%A4%AA%E9%83%8E&email=user@example.com
// encodeURIComponent - すべての特殊文字をエンコード
console.log(encodeURIComponent(url));
// https%3A%2F%2Fexample.com%2Fpath%3Fname%3D%E7%94%B0%E4%B8%AD%E5%A4%AA%E9%83%8E%26email%3Duser%40example.com

encodeURIはURLの構造を保持しますが、encodeURIComponentはすべての特殊文字をエンコードします。

適切な使い分け

どちらをいつ使うべきか見てみましょう。

function demonstrateEncodingDifferences() {
const baseUrl = "https://example.com/api";
const path = "users/search";
const params = {
name: "田中 太郎",
email: "user@example.com",
query: "JavaScript & React"
};
// 正しい方法: パラメータ値のみencodeURIComponent
const correctUrl = baseUrl + "/" + path + "?" +
Object.entries(params)
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
.join('&');
console.log("正しいエンコード:", correctUrl);
// 間違った方法: URL全体をencodeURIComponent
const wrongUrl = encodeURIComponent(baseUrl + "/" + path);
console.log("間違ったエンコード:", wrongUrl);
// encodeURIの使用例(完全なURLを一度にエンコード)
const fullUrl = `${baseUrl}/${path}?name=田中 太郎&email=user@example.com`;
console.log("encodeURI使用:", encodeURI(fullUrl));
}
demonstrateEncodingDifferences();

基本的には、パラメータの値だけをencodeURIComponentでエンコードするのが正しい方法です。

よくある間違いと対処法

二重エンコードの問題

同じ文字列を何度もエンコードしてしまう問題です。

function avoidDoubleEncoding(value) {
// 既にエンコードされているかチェック
try {
const decoded = decodeURIComponent(value);
const reencoded = encodeURIComponent(decoded);
// 元の値と再エンコード値が同じ場合、既にエンコード済み
if (reencoded === value) {
console.log("既にエンコード済み:", value);
return value;
} else {
console.log("エンコードが必要:", value);
return encodeURIComponent(value);
}
} catch (error) {
// デコードエラーの場合、エンコードされていない
console.log("エンコードします:", value);
return encodeURIComponent(value);
}
}
// テスト
console.log(avoidDoubleEncoding("hello world")); // エンコード
console.log(avoidDoubleEncoding("hello%20world")); // エンコード済み

この関数は、既にエンコードされているかどうかをチェックして、必要な場合のみエンコードします。

null・undefinedの処理

予期しない値が渡された場合の対処法です。

function safeEncode(value) {
if (value === null || value === undefined) {
return '';
}
return encodeURIComponent(value.toString());
}
// テスト
console.log(safeEncode("Hello")); // Hello
console.log(safeEncode(null)); // ''
console.log(safeEncode(undefined)); // ''
console.log(safeEncode(123)); // 123

null や undefined が渡されても安全に処理できます。

配列の処理

配列をURLパラメータとして渡す場合の処理方法です。

function encodeArrayParam(key, array) {
return array
.filter(item => item !== null && item !== undefined)
.map(item => `${encodeURIComponent(key)}=${encodeURIComponent(item)}`)
.join('&');
}
// 使用例
const tags = ['JavaScript', 'プログラミング', 'Web開発'];
const encoded = encodeArrayParam('tags', tags);
console.log(encoded);
// tags=JavaScript&tags=%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&tags=Web%E9%96%8B%E7%99%BA

配列の各要素を個別にエンコードして、同じパラメータ名で複数の値を送信できます。

セキュリティの考慮

XSS対策

セキュリティも考慮した安全なURL生成方法です。

function createSafeUrl(baseUrl, params) {
// パラメータを適切にエンコード
const queryString = Object.entries(params)
.filter(([key, value]) => value !== null && value !== undefined)
.map(([key, value]) => {
// HTMLタグを除去
const cleanValue = value.toString().replace(/<[^>]*>/g, '');
return `${encodeURIComponent(key)}=${encodeURIComponent(cleanValue)}`;
})
.join('&');
return queryString ? `${baseUrl}?${queryString}` : baseUrl;
}

この関数は、HTMLタグを除去してからエンコードするため、XSS攻撃のリスクを軽減できます。

入力値の検証

function validateAndEncode(value, maxLength = 1000) {
if (typeof value !== 'string') {
throw new Error('文字列である必要があります');
}
if (value.length > maxLength) {
throw new Error(`文字列が長すぎます(最大${maxLength}文字)`);
}
// 危険な文字列パターンをチェック
const dangerousPatterns = [
/<script/i,
/javascript:/i,
/data:/i,
/vbscript:/i
];
for (const pattern of dangerousPatterns) {
if (pattern.test(value)) {
throw new Error('安全でない文字列が含まれています');
}
}
return encodeURIComponent(value);
}

入力値を事前に検証することで、セキュリティリスクを軽減できます。

まとめ

JavaScriptのencodeURIComponentを使ったURLエンコードについて、基礎から実践まで詳しく解説しました。

重要なポイント

  • URLパラメータには必ずencodeURIComponentを使用
  • encodeURIとencodeURIComponentの使い分けを理解
  • 二重エンコードや特殊値の処理に注意
  • セキュリティ対策も忘れずに実装

実践のコツ

  • URLの各部分に応じて適切なエンコード方法を選択
  • エラーハンドリングと入力値検証を実装
  • 再利用可能な関数やクラスを作成
  • 安全性を常に意識した実装

URLエンコードは、Web開発において必須の知識です。 適切なエンコード処理により、安全で信頼性の高いWebアプリケーションを構築できるようになります。

ぜひ今日から、これらの技術を実際のプロジェクトで積極的に活用してみてください!

関連記事