目次
概要
文字列内の指定された位置にある文字を取得する charAt() メソッドは、入力値の解析や特定のパターン判定において重要な役割を果たします。 本記事では、このメソッドを活用して、ユーザーが入力した文字の「先頭1文字」に基づき、名簿リストをリアルタイムにフィルタリング(絞り込み)する検索UIの実装方法を解説します。
仕様(入出力)
- 入力: 検索ボックスへのテキスト入力。
- 出力: 入力されたテキストの「1文字目」と、リスト内のアイテムの「読み仮名(または英語名)の1文字目」が一致するものだけを表示する。
- 動作:
- 入力が空の場合は全件表示する。
- 入力がある場合、それぞれの先頭文字を比較し、不一致の要素を非表示にする。
基本の使い方
charAt(index) メソッドを使用します。引数には取得したい文字のインデックス(0から始まる整数)を指定します。
const text = "Engineering";
// 先頭(0番目)の文字を取得
console.log(text.charAt(0)); // 出力: "E"
// 3番目の文字を取得
console.log(text.charAt(3)); // 出力: "i"
// 範囲外を指定した場合
console.log(text.charAt(99)); // 出力: ""(空文字)
コード全文(HTML / JavaScript)
HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Employee Filter</title>
<style>
body { font-family: sans-serif; padding: 20px; }
.search-box { margin-bottom: 20px; padding: 8px; width: 100%; max-width: 300px; }
.employee-list { list-style: none; padding: 0; }
.employee-item {
padding: 10px;
border-bottom: 1px solid #eee;
display: block;
}
/* 非表示用クラス */
.hidden { display: none; }
</style>
</head>
<body>
<h3>従業員ディレクトリ検索</h3>
<p>名前の頭文字を入力してください(例: "K" → Kate, Kevin)</p>
<input type="text" id="searchInput" class="search-box" placeholder="頭文字で検索...">
<ul id="employeeList" class="employee-list">
<li class="employee-item" data-name="Alice" data-initial="A">Alice Johnson</li>
<li class="employee-item" data-name="Bob" data-initial="B">Bob Smith</li>
<li class="employee-item" data-name="Charlie" data-initial="C">Charlie Brown</li>
<li class="employee-item" data-name="David" data-initial="D">David Wilson</li>
<li class="employee-item" data-name="Eve" data-initial="E">Eve Davis</li>
<li class="employee-item" data-name="Frank" data-initial="F">Frank Miller</li>
</ul>
<script src="app.js"></script>
</body>
</html>
javascript
/**
* 検索ボックスとリスト要素の参照を取得
*/
const searchInput = document.querySelector("#searchInput");
const employeeItems = document.querySelectorAll(".employee-item");
/**
* 入力イベントを監視してフィルタリングを実行
*/
searchInput.addEventListener("input", () => {
// 入力値を取得し、前後の空白を除去
const inputValue = searchInput.value.trim();
employeeItems.forEach((item) => {
// 入力が空の場合は「hidden」クラスを外して全表示し、次の要素へ
if (inputValue === "") {
item.classList.remove("hidden");
return;
}
// データ属性から検索対象の頭文字を取得(大文字化して正規化)
const targetInitial = item.dataset.initial.toUpperCase();
// 入力値の先頭1文字を取得(大文字化して正規化)
const inputInitial = inputValue.charAt(0).toUpperCase();
// 頭文字同士を比較
if (inputInitial === targetInitial) {
item.classList.remove("hidden");
} else {
item.classList.add("hidden");
}
});
});
カスタムポイント
- データ属性の拡張: 今回は
data-initialを使用しましたが、日本語対応のためにdata-kana(例: “タナカ”)を持たせ、data-kana.charAt(0)と比較することで「あかさたな」検索に応用できます。 - 比較条件の変更: 現在は「先頭1文字」の完全一致ですが、
inputInitialを小文字に変換せず区別したり、数字のみを対象にするなどのロジック変更が可能です。 - 表示切り替えのアニメーション:
display: noneの切り替えだけでなく、CSSのopacityやtransitionを組み合わせることで、フィルタリング時に滑らかな視覚効果を与えることができます。
注意点
- インデックス範囲外のアクセス:
charAt()は存在しないインデックス(文字列長以上)を指定すると空文字""を返します。undefinedにはなりませんが、ロジック上で空文字との比較が発生しないよう注意が必要です。 - サロゲートペア(絵文字など)の扱い:
charAt()は16ビット単位(UTF-16コードユニット)で文字を取得するため、絵文字や一部の漢字(𠮷など)は正しく1文字として取得できず、文字化けしたようなデータ(上位サロゲートのみ)が返る場合があります。これらを厳密に扱う場合はArray.from(str)[0]などの手法を検討してください。
応用
入力文字数に応じた動的判定
入力が1文字の場合は「頭文字検索」、2文字以上の場合は通常の「部分一致検索(includes)」に切り替えるハイブリッドな実装例です。
const keyword = inputValue.toUpperCase();
if (keyword.length === 1) {
// 1文字なら頭文字判定 (charAt)
const isMatch = item.dataset.name.toUpperCase().charAt(0) === keyword;
/* 表示切り替え処理 */
} else {
// 2文字以上なら部分一致判定 (includes)
const isMatch = item.dataset.name.toUpperCase().includes(keyword);
/* 表示切り替え処理 */
}
まとめ
charAt() メソッドは特定位置の文字取得において最も基本的かつ高速な手段です。配列のインデックスアクセス記法(str[0])と比較しても互換性が高く意図が明確であるため、特に今回のような「頭文字判定」や「固定フォーマットのコード解析」といった場面では堅実な選択肢となります。ただし、多言語対応や特殊文字を含む現代的なアプリケーションにおいては、サロゲートペアへの理解を持った上で採用を判断すべきです。
