フォームの入力文字数チェック、テキストの省略表示、API のリクエスト制限など、文字列の長さを取得する操作はフロントエンド開発のあらゆる場面で必要になります。JavaScript では length プロパティで簡単に取得できますが、絵文字(サロゲートペア)を含む場合は想定と異なる値が返ることがあり注意が必要です。
・length プロパティの基本と戻り値
・length が返すのは「UTF-16 コードユニット数」
・サロゲートペア(絵文字)で length が想定と異なる理由と対策
・Intl.Segmenter で書記素クラスタ単位の正確なカウント
・バイト数(UTF-8)の取得方法
・配列の length との違い
・空文字判定・入力文字数制限・テキスト省略表示の実務パターン
length プロパティの基本
const len = str.length; // 戻り値: 文字列の UTF-16 コードユニット数(0 以上の整数) // 読み取り専用(代入しても変更されない)
console.log("Hello".length); // 5
console.log("こんにちは".length); // 5
console.log("".length); // 0(空文字)
console.log(" ".length); // 1(半角スペース)
console.log("Hello World".length); // 11(スペースも1文字)
length はプロパティです。メソッドではないため () を付けません。
// "Hello".length() // TypeError: "Hello".length is not a function "Hello".length // 5(正しい)
length が返すのは「UTF-16 コードユニット数」
JavaScript の文字列は内部的に UTF-16 でエンコードされています。length が返す値は「見た目の文字数」ではなく、UTF-16 コードユニットの数です。
多くの文字(ASCII、ひらがな、カタカナ、漢字の大半)は 1 コードユニット = 1 文字なので問題ありませんが、一部の文字は 2 コードユニットを使います。
| 文字の種類 | コードユニット数 | 例 |
|---|---|---|
| ASCII(半角英数字) | 1 | "A".length → 1 |
| ひらがな・カタカナ | 1 | "あ".length → 1 |
| 基本的な漢字 | 1 | "漢".length → 1 |
| 絵文字(サロゲートペア) | 2 | "?".length → 2 |
| 一部の漢字(BMP外) | 2 | "?".length → 2 |
サロゲートペア(絵文字)で length が想定と異なる問題
絵文字や一部の漢字はサロゲートペア(2 つの UTF-16 コードユニットで 1 文字を表現)のため、length は見た目の文字数より大きい値を返します。
const text = "Hello?"; console.log(text.length); // 7("Hello"=5 + ?=2) console.log([...text].length); // 6(見た目の文字数)
スプレッド構文で見た目の文字数を取得する
スプレッド構文 [...str] は文字列を Unicode コードポイント単位で分割するため、サロゲートペアを 1 文字として扱います。
function visualLength(str) {
return [...str].length;
}
console.log(visualLength("Hello?")); // 6
console.log(visualLength("こんにちは?")); // 6
console.log(visualLength("?野家")); // 3
結合絵文字(ZWJ シーケンス)の注意点
家族絵文字や国旗絵文字など、複数のコードポイントが結合した「結合絵文字」は、スプレッド構文でも正確にカウントできません。
const family = "????"; // 家族絵文字(ZWJ シーケンス) console.log(family.length); // 11 console.log([...family].length); // 7(ZWJ と各絵文字がバラバラに)
このようなケースで正確にカウントするには Intl.Segmenter を使います。
Intl.Segmenter で書記素クラスタ単位のカウント
function graphemeLength(str) {
const segmenter = new Intl.Segmenter("ja", { granularity: "grapheme" });
return [...segmenter.segment(str)].length;
}
console.log(graphemeLength("Hello?")); // 6
console.log(graphemeLength("????")); // 1(正確!)
console.log(graphemeLength("??")); // 1(国旗も正確)
| 方法 | 絵文字 | 結合絵文字 | ブラウザ対応 |
|---|---|---|---|
str.length |
× 2倍になる | × 大幅に多い | 全ブラウザ |
[...str].length |
○ 正確 | × 分割される | 全ブラウザ |
Intl.Segmenter |
○ 正確 | ○ 正確 | Chrome 87+ / Safari 15.4+(IE/Firefox 非対応) |
[...str].length で妥協する方法があります。文字列のバイト数を取得する方法
length は「文字数」であり「バイト数」ではありません。UTF-8 でのバイト数が必要な場合は TextEncoder を使います。
function byteLength(str) {
return new TextEncoder().encode(str).length;
}
console.log(byteLength("ABC")); // 3(ASCII: 1バイト×3)
console.log(byteLength("あいう")); // 9(日本語: 3バイト×3)
console.log(byteLength("?")); // 4(絵文字: 4バイト)
| 文字 | length(文字数) | UTF-8 バイト数 |
|---|---|---|
"A" |
1 | 1 |
"あ" |
1 | 3 |
"?" |
2 | 4 |
配列の length との違い
文字列の length は読み取り専用ですが、配列の length は読み書きの両方が可能です。
| 比較項目 | 文字列の length | 配列の length |
|---|---|---|
| 戻り値 | UTF-16 コードユニット数 | 要素数 |
| 書き込み | 不可(代入しても無視される) | 可能(要素数を増減できる) |
// 文字列: 読み取り専用 const str = "Hello"; console.log(str.length); // 5 // str.length = 3; // 無視される(strict mode ではエラー) // 配列: 書き込み可能 const arr = [1, 2, 3, 4, 5]; arr.length = 3; console.log(arr); // [1, 2, 3](末尾が切り捨てられる)
実務でよく使うパターン
空文字列の判定
function isEmpty(str) {
return !str || str.length === 0;
}
console.log(isEmpty("")); // true
console.log(isEmpty(null)); // true
console.log(isEmpty(undefined)); // true
console.log(isEmpty("Hello")); // false
// 空白のみも空とみなす場合
function isBlank(str) {
return !str?.trim();
}
console.log(isBlank(" ")); // true
入力文字数のリアルタイムカウンター
<textarea id="message" maxlength="200" placeholder="メッセージを入力"></textarea> <p><span id="charCount">0</span> / 200</p>
const textarea = document.getElementById("message");
const counter = document.getElementById("charCount");
textarea.addEventListener("input", () => {
counter.textContent = textarea.value.length;
});
テキストの省略表示(truncate)
function truncate(str, maxLength) {
if (str.length <= maxLength) return str;
return str.slice(0, maxLength) + "...";
}
console.log(truncate("JavaScriptで文字列の長さを取得する方法", 15));
// "JavaScriptで文字列の..."
パスワードの長さバリデーション
function validatePassword(password) {
const errors = [];
if (password.length < 8) {
errors.push("8文字以上で入力してください");
}
if (password.length > 64) {
errors.push("64文字以下で入力してください");
}
return errors.length === 0
? { valid: true }
: { valid: false, errors };
}
console.log(validatePassword("abc"));
// { valid: false, errors: ["8文字以上で入力してください"] }
関連記事
- 文字列のバイト数を取得する方法 — TextEncoder・UTF-8 バイト数
- 全角を2文字、半角を1文字としてカウントする方法
- サロゲートペア文字列を正しく扱う方法 — for-of・スプレッド構文
- 空文字列の判定方法 — length・真偽値・trim()
- slice の使い方 — 文字列の切り出し
- charAt の使い方 — 文字列から 1 文字を取得
よくある質問
length は UTF-16 コードユニット数を返します。絵文字はサロゲートペア(2 コードユニット)のため、見た目 1 文字でも length は 2 になります。見た目の文字数を取得するには [...str].length を使ってください。null.length や undefined.length は TypeError になります。事前に if (!str) でチェックするか、オプショナルチェーニング str?.length ?? 0 を使うと安全です。str.length のように () なしでアクセスします。str.length() と書くと TypeError になります。\n(改行)は 1、\t(タブ)は 1、\r\n(Windows 改行)は 2 としてカウントされます。new TextEncoder().encode(str).length で UTF-8 バイト数を取得できます。API のサイズ制限やデータベースのカラム幅チェックではバイト数での判定が必要です。まとめ
JavaScript で文字列の長さを取得するには length プロパティを使います。
- 基本:
str.lengthで UTF-16 コードユニット数を返す - サロゲートペア: 絵文字は length が 2 になる →
[...str].lengthで対策 - 結合絵文字: ZWJ シーケンスは
Intl.Segmenterで正確にカウント - バイト数:
new TextEncoder().encode(str).lengthで UTF-8 バイト数 - 配列との違い: 文字列の length は読み取り専用、配列は書き込み可能
入力バリデーションやテキスト省略など日常的に使うプロパティですが、絵文字を含むケースではカウント方法の選択が重要です。要件に応じて使い分けてください。