【JavaScript】文字列の後ろから指定した文字数を取得する方法|slice(-n)・substringと末尾0・絵文字対策まで解説

JavaScriptで「文字列の末尾から3文字だけ取り出したい」のように、後ろ(末尾)から指定した文字数を取得したい場面はよくあります。カード番号の下4桁を取り出したり、ファイルや識別子の末尾の区分だけを見たりするケースです。

結論はシンプルで、負のインデックスに対応した slice(-文字数) を使います。この記事では基本の取得方法から、substring() での書き方、「末尾0文字」を取りたいのに全文が返る -0 の罠、絵文字を含むときの挙動、そして紛らわしい「末尾N文字を削除して前を取得」との違いまで解説します。

この記事の結論:末尾からN文字を取得するなら str.slice(-n) が基本です。(末尾からN文字を削除して前が欲しい場合は str.slice(0, -n) と、引数の渡し方で逆の意味になる点に注意してください。)
スポンサーリンク

slice() で末尾からN文字を取得する(推奨)

slice() は負の値を「末尾からの位置」として扱えるため、slice(-文字数) だけで末尾N文字を取得できます。

slice(-n) で末尾N文字を取得
const str = "abcdefg";
const n = 3; // 取得したい文字数

const result = str.slice(-n);
console.log(result); // "efg"

substring() で取得する

substring()負のインデックスに対応していないため、開始位置を 文字列の長さ − 文字数 で計算して渡します。

substring() で末尾N文字を取得
const str = "abcdefg";
const n = 3;

const result = str.substring(str.length - n);
console.log(result); // "efg"
先頭からN文字を取得したい場合は姉妹記事先頭から指定した文字数を取得する方法、途中から文字数を指定するなら開始位置と文字数を指定して取得する方法を参照してください。

【重要】「末尾0文字」と文字数オーバーの挙動

変数で文字数を渡すとき、slice(-n) にはn が 0 のとき全文が返るという落とし穴があります。JavaScriptでは -00 と等しいため、slice(-0)slice(0) と同じ=先頭からの全文になるためです。

-0 の罠と文字数オーバー
const str = "abcdefg";

console.log(str.slice(-0));  // "abcdefg"(""ではなく全文! -0 は 0 と同じ)
console.log(str.slice(-10)); // "abcdefg"(文字数が長すぎても全文・エラーなし)

// n が 0 でも安全に「空文字」にしたいなら length 基準で書く
function lastN(str, n) {
  return str.slice(str.length - n); // n=0 のとき slice(length) → ""
}
console.log(lastN(str, 0)); // ""(意図通り0文字)
console.log(lastN(str, 3)); // "efg"
n が動的に 0 になりうる場合は注意。slice(-n)n === 0 で全文を返してしまいます。slice(str.length - n)n === 0 ? "" : str.slice(-n) のように書くと安全です。なお文字数が文字列より長い場合は、どちらも全文を返すだけでエラーにはなりません

【混同注意】「末尾N文字を削除して前を取得」との違い

「後ろからN文字」も、末尾N文字を取得するのか、末尾N文字を削除して前を取得するのかで真逆になります。slice() の引数で切り替わるので整理しておきましょう。

取得 vs 削除(前を取得)
const str = "abcdefg";
const n = 3;

// 末尾から n 文字を「取得」する
console.log(str.slice(-n));   // "efg"

// 末尾から n 文字を「削除」して前を取得する
console.log(str.slice(0, -n)); // "abcd"
「特定の文字より後ろをまるごと削除したい」場合は指定した文字以降の文字列を削除する方法も参考になります。

【注意】絵文字・サロゲートペアを含む場合

slice() はUTF-16のコード単位で数えるため、末尾の文字が絵文字(😀 など)のように2コード単位で1文字のサロゲートペアだと、途中で切れて文字化けします。見た目の1文字(コードポイント)単位で取得したいときは [...str] で配列化してから切り出します。

コードポイント単位で末尾N文字
// 末尾が絵文字(\u{1F600} = 絵文字1文字)の文字列
const str = "ab\u{1F600}";

console.log(str.slice(-1)); // 壊れた半端な文字(絵文字の片割れ)

// 対策: コードポイント単位で取得
function lastChars(str, n) {
  if (n <= 0) return ""; // slice(-0) は全文が返るため 0 以下は明示的に空文字に
  return [...str].slice(-n).join("");
}
console.log(lastChars(str, 1)); // 絵文字1文字(壊れない)
console.log(lastChars(str, 2)); // "b" + 絵文字

方法の使い分け

やりたいこと 書き方
末尾からN文字を取得 str.slice(-n) / str.substring(str.length - n)
末尾N文字を削除して前を取得 str.slice(0, -n)
n が 0 でも安全に取得 str.slice(str.length - n)
絵文字を崩さず末尾N文字 [...str].slice(-n).join("")
先頭からN文字を取得 str.slice(0, n)詳細

実用例:カード番号の下4桁を取得する

伏せ字表示などでよく使う「末尾4桁」も slice(-4) で簡潔に取得できます。

下4桁の取得
const card = "1234567812345678";

const last4 = card.slice(-4);
console.log(last4); // "5678"

// 下4桁以外を伏せ字にする
const masked = "*".repeat(card.length - 4) + last4;
console.log(masked); // "************5678"

よくある質問(FAQ)

Q末尾からN文字を取得する一番簡単な方法は?
Astr.slice(-n) です。負の値を渡すと末尾からの位置として扱われるため、slice(-3) で末尾3文字を取得できます。substring() は負の値に対応しないので str.substring(str.length - n) と書きます。
Qslice(-n) と slice(0, -n) は何が違うのですか?
A意味が逆です。slice(-n)末尾からN文字を取得"efg")、slice(0, -n)末尾N文字を削除して前を取得"abcd")します。
Qslice(-n) で「末尾0文字」を取りたいのに全文が返るのはなぜ?
AJavaScriptでは -00 と等しく、slice(-0)slice(0)(全文)になるためです。n が 0 になりうる場合は str.slice(str.length - n)n === 0 ? "" : str.slice(-n) と書くと意図どおり空文字になります。
Q絵文字を含むと末尾N文字がずれるのはなぜですか?
Aslice() はUTF-16のコード単位で数え、絵文字(サロゲートペア)は2単位で1文字だからです。[...str].slice(-n).join("") のようにコードポイント単位の配列にしてから取得すると、見た目の文字数で正しく切り出せます。

まとめ

JavaScriptで文字列の後ろから指定した文字数を取得する方法のポイントを整理します。

  • 末尾からN文字の取得は str.slice(-n)substring(str.length - n) も同じ)
  • slice(-0) は全文が返る-0 === 0)。n が 0 になりうるなら slice(str.length - n)
  • 文字数が長すぎてもエラーにならず全文が返る
  • slice(-n)(取得)と slice(0, -n)(末尾N文字を削除して前)は逆の意味
  • 絵文字を含むなら [...str].slice(-n).join("") でコードポイント単位に

対になる先頭から指定した文字数を取得する方法や、開始位置と文字数を指定して取得する方法、特定の文字の直前直後の1文字を取得する記事もあわせて確認すると理解が深まります。