やあ、よく来たな。現場のコードレビューで「とりあえず`trim()`しておけばいいでしょ」なんて雑な処理を見かけるたびに、私は少しだけ眉をひそめてしまうんだ。
今日は、地味だが実に奥が深い、そして「意図のあるコード」を書くために欠かせない`String.prototype.trimEnd()`について話をしよう。
「末尾の空白を消すだけでしょ?」と思ったなら、少しだけ私の話を聞いてほしい。プロの仕事というのは、その「たかが空白」をどう扱うかに宿るものなんだ。
—
なぜ `trim()` ではなく `trimEnd()` なのか?
フロントエンドの実務において、ユーザーの入力値やAPIから降ってくる文字列は、常に我々の想定を裏切ってくる。
例えば、チャットアプリのメッセージ送信や、マークダウンエディタのリアルタイムプレビューを想像してみてくれ。ユーザーが「行頭のインデント(空白)」を意図的に入れている場合、`trim()` を使ってしまうとその大切な意図をバッサリ切り捨ててしまうことになる。
「前方の意図は守り、後方のゴミだけを掃除する。」
この繊細な制御を実現するのが `trimEnd()` だ。ES2019(ES10)で正式に標準化されたこのメソッドは、かつて `trimRight()` と呼ばれていたもののエイリアスだが、現在は `padStart` や `padEnd` との対称性を保つために `trimEnd` を使うのがモダンな開発者のエチケットだ。
—
ブラウザの裏側で何が起きているか
我々が `str.trimEnd()` を呼び出したとき、V8(Chrome/Node.js)や JavaScriptCore(Safari)といったエンジンの中では、単にループを回している以上の最適化が行われている。
1. 文字列の走査: エンジンは文字列の末尾(インデックス `length – 1`)から逆方向にスキャンを開始する。
2. 空白文字の判定: ここが重要だ。JavaScriptにおける「空白」は、単なる半角スペース(`U+0020`)だけじゃない。タブ(`\t`)、改行(`\n`)、さらには `\u3000`(全角スペース)や `\u00A0`(不壊空格)といったUnicodeの「White_Space」プロパティを持つ文字すべてを対象としている。
3. スライス処理: 最初の「空白ではない文字」が見つかった瞬間、走査を止める。そして、文字列の開始位置からその文字までの範囲を、新しい文字列として切り出す(実際には、元の文字列のメモリを参照しつつ、オフセットを調整するような高度な最適化が行われることもある)。
「正規表現で `replace(/\s+$/, ”)` と書けばいいじゃないか」と言う若手もいるが、エンジンネイティブの `trimEnd()` は、正規表現エンジンのオーバーヘッドがない分、パフォーマンス的に極めて有利だ。大量のログデータなどを処理する際は、この差が効いてくる。
—
実務で使える実践コード
では、現場でそのまま使えるような、少し気の利いたサンプルを紹介しよう。単にメソッドを呼ぶだけではなく、実務で遭遇しがちな「複数行テキストの整形」をテーマにしてみた。
/
- ユーザーが入力した複数行のコメントをクリーンアップする関数
- 各行の行頭インデントは保持しつつ、行末の無駄なスペースだけを削除する。
- これにより、コードブロックなどの意図的なレイアウトを壊さずに済む。
/
const sanitizeUserComment = (rawText) => {
if (typeof rawText !== ‘string’) return ”;
return rawText
.split(‘\n’) // 行ごとに分割
.map(line => {
// trim() を使うと行頭のインデントまで消えてしまうため、
// ここではあえて trimEnd() を採用する。
return line.trimEnd();
})
.join(‘\n’); // 再び結合
};
// — 動作確認 —
const dirtyInput =
` function hello() {
console.log(“world”); \t\t
} `;
const cleanedInput = sanitizeUserComment(dirtyInput);
console.log(“— 変換前 (末尾に不可視の空白あり) —“);
console.log(`”${dirtyInput}”`);
console.log(“\n— 変換後 (行頭インデントは維持、行末のみ削除) —“);
console.log(`”${cleanedInput}”`);
/
出力結果のイメージ:
” function hello() {” <- 行末のスペースが消える
" console.log("world");" <- タブ文字(\t)も綺麗に消える
" }" <- 最後の空白もスッキリ
/
---
現場のシニアが教える「ハマりどころ」
ここで一つ、君たちにアドバイスだ。`trimEnd()` は万能に見えるが、「全角スペース」の扱いには注意が必要だ。
近年のモダンブラウザの JavaScript エンジンは、Unicode 仕様に準拠しているため、全角スペース(`\u3000`)も `trimEnd()` でしっかり削ってくれる。しかし、古い環境や特定のランタイム、あるいは「全角スペースは文字として残したい」という特殊な要件がある場合は、この挙動が仇となることもある。
「空白」の定義がプロジェクトによって異なる場合、安易に組み込みメソッドに頼るのではなく、一歩立ち止まって「何をもってゴミ(空白)とするか」を定義する。これがシニアへの第一歩だ。
—
まとめ:細部にこそ魂を込めろ
`trimEnd()` は、決して派手なメソッドではない。しかし、これを選択するということは、君が「ユーザーの入力意図を尊重し、かつデータとしての整合性を保とうとしている」というプロ意識の現れなんだ。
- `trim()`:前後まるごと綺麗にする(入力フォームのユーザー名など)。
- `trimStart()`:前方の余白を消す(特定のフォーマット解析など)。
- `trimEnd()`:後方のゴミだけを消す(コードエディタ、メッセージ投稿、整形済みテキストなど)。
適材適所。これがアーキテクチャの基本だ。
次に君が書くコードの中で、このメソッドが「意図を持って」使われているのを楽しみにしているよ。
さあ、エディタに戻って。最高のコードを書いてこい。

コメント