属性値の文字列化とは何か
「属性値の文字列化」は、DOM の属性に値を入れるとき、数値や真偽値、オブジェクトなど“文字列以外”の値を安全・意図通りの文字列に変換してから設定することです。ここが重要です:HTML の属性は最終的に「文字列」で扱われます。null や undefined、true/false、数値、配列・オブジェクトをそのまま渡すと予期せぬ表示や挙動につながるため、変換のルールを決めておくと堅牢になります。
setAttribute / getAttribute の基本と型の扱い
文字列化の最短パターン
<button id="buy">購入</button>
<script>
const btn = document.getElementById("buy");
// 属性は文字列で持つのが基本
btn.setAttribute("data-sku", String(12345)); // "12345"
btn.setAttribute("title", String("ようこそ")); // "ようこそ"
// 読み取り:見つからなければ null
console.log(btn.getAttribute("data-sku")); // "12345"
console.log(btn.getAttribute("data-missing")) // null
</script>
HTMLgetAttribute は「文字列か null」を返します。ここが重要です:属性に入れる値は原則 String(…) で明示的に文字列化する。undefined やオブジェクトをうっかり渡さない習慣が大事です。
よくある型の落とし穴と安全な変換
null / undefined は空文字に
function toAttrString(value) {
return String(value ?? ""); // null/undefined を "" に
}
el.setAttribute("data-note", toAttrString(maybeNull));
JavaScriptここが重要です:String(null) は “null”、String(undefined) は “undefined”。意図せずその文字が表示されがちなので、空文字へ丸めるのが安全です。
数値は String(number) で確実に
el.setAttribute("data-count", String(0)); // "0"
JavaScript数値の 0 は falsy ですが、属性には意味のある値です。ここが重要です:0 を消さないように明示的に文字列化。
真偽値は「文字列」か「boolean属性」で扱う
<input id="agree" type="checkbox">
<script>
const box = document.getElementById("agree");
// 文字列として持つとき(data-* 等)
box.setAttribute("data-enabled", String(true)); // "true"
// boolean 属性は「存在が真」。"false" と書いても真になる
box.toggleAttribute("disabled", false); // 無効化しない
box.toggleAttribute("disabled", true); // 無効化する
// 悪い例:disabled="false" でも disabled は有効(存在しているため)
box.setAttribute("disabled", "false"); // ダメ。結果は無効化される
</script>
HTMLここが重要です:disabled、checked、required などの boolean 属性は「値の文字列」ではなく「有無」で判定されます。toggleAttribute/removeAttribute を使い、”false” を文字列で書かない。
data-* と JSON の文字列化(複合データの安全な持ち方)
data-* は“文字列だけ”。JSON 化して持つ
<button id="item"></button>
<script>
const btn = document.getElementById("item");
const payload = { id: 42, name: "Apple", tags: ["fruit", "red"] };
btn.setAttribute("data-payload", JSON.stringify(payload)); // 文字列化
// 読むとき
const parsed = JSON.parse(btn.getAttribute("data-payload") ?? "{}");
</script>
HTMLここが重要です:data-* は文字列専用。複合データは JSON.stringify/parse のペアで扱うとシンプルで安全です。配列やオブジェクトを dataset に直接入れない。
URL・クエリの文字列化とエンコード(必須の作法)
パラメータは encodeURIComponent でエンコード
const base = "/search";
const q = "赤い 果物";
const url = `${base}?q=${encodeURIComponent(q)}`; // スペースや記号を安全化
link.setAttribute("href", url);
JavaScriptここが重要です:URL にユーザー入力を混ぜるときは必ずエンコード。未エンコードは壊れた URL や意図しない解釈の原因になります。
複数パラメータは URLSearchParams を活用
const params = new URLSearchParams({ q: "バナナ", page: 2 });
a.setAttribute("href", `/items?${params}`);
JavaScriptここが重要です:文字列結合はミスが増えます。URLSearchParams で「正しく文字列化」する癖を。
プロパティと属性の違い(文字列化に響くポイント)
属性は文字列、プロパティは型付きで反映されることがある
<input id="price" type="number">
<script>
const el = document.getElementById("price");
el.setAttribute("value", String(3.14)); // 属性:文字列
el.value = String(3.14); // プロパティ:フォームの現在値に反映
// URL 系は解決後の文字列に見えることがある
const a = document.createElement("a");
a.setAttribute("href", "/about"); // 属性は "/about"
console.log(a.href); // プロパティは絶対 URL に解決(例: "https://example.com/about")
</script>
HTMLここが重要です:表示・挙動に関係する「現在値」はプロパティで制御し、静的な「初期値・メタ」は属性を使う。URL はプロパティで正規化される違いを覚えておくと混乱しない。
安全性:文字列化とインジェクション回避(必ず DOM API を使う)
setAttribute は自動で値を属性として扱う(HTMLを作らない)
el.setAttribute("title", '<img src=x onerror=alert(1)>'); // ただの文字列として属性に入る
JavaScriptDOM API は「属性の値」を作るだけで、勝手に HTML を展開しません。ここが重要です:属性・テキストは DOM メソッドで設定する。innerHTML で文字列結合するとインジェクションの危険が跳ね上がります。
テキストは textContent、属性は setAttribute
title.textContent = userText; // 画面表示文言は文字で
button.setAttribute("aria-label", userText); // アクセシビリティ属性も文字で
JavaScriptここが重要です:外部データは常に“文字”として入れる。構造を文字列で作らない。
実践例:安全・明確な属性設定ユーティリティ
toAttrString と toggleBoolAttr を用意する
function toAttrString(v) {
return String(v ?? ""); // null/undefined を "" に丸める
}
function toggleBoolAttr(el, name, on) {
el.toggleAttribute(name, !!on); // boolean 属性は有無で管理
}
// 使い方
const btn = document.querySelector("#buy");
btn.setAttribute("data-sku", toAttrString(12345));
btn.setAttribute("data-note", toAttrString(null)); // ""
toggleBoolAttr(btn, "disabled", false); // 付けない
toggleBoolAttr(btn, "disabled", true); // 付ける
// JSON を属性に持たせる
const payload = { id: 7, tags: ["new"] };
btn.setAttribute("data-payload", JSON.stringify(payload));
JavaScriptここが重要です:変換ルールを関数化して“毎回同じ挙動”にする。プロジェクト全体の一貫性と安全性が上がります。
まとめ
属性値は最後は「文字列」。null/undefined は空文字に揃え、数値は String(number) で明示的に、真偽は「文字列」ではなく boolean 属性の有無で管理する。複合データは JSON に文字列化して data-* に持たせ、URL は必ずエンコード。表示や現在値はプロパティ、メタや初期値は属性——この役割分担を守り、常に DOM API(setAttribute / textContent)で安全に扱う。小さなユーティリティで文字列化を標準化すれば、初心者でも意図通りで堅牢な属性設定が書けます。
