文字列複製の新常識:`repeat()` を使いこなす、あるいは「なぜ自作してはいけないのか」
現場でコードレビューをしていると、今でもたまに見かけるんだ。「文字列をN回繰り返す」という目的のために、わざわざ `for` ループを回して変数に加算していくコードをね。
気持ちはわかる。昔のJavaScript(IEの時代)ならそれが正攻法だった。でも、今はモダンな時代だ。`String.prototype.repeat()` が標準で用意されている。今回は、このメソッドの「仕様の裏側」と、現場で遭遇するちょっとした落とし穴について、シニアの視点から深掘りしていこう。
—
1. `repeat()` の基本と「なぜ速いのか」
`repeat()` はシンプルだ。対象の文字列を、指定した回数だけ連結して新しい文字列を返す。
// 基本的な使い方
const emoji = ‘🚀’;
console.log(emoji.repeat(3)); // “🚀🚀🚀”
では、なぜわざわざネイティブメソッドを使うべきなのか? それは単に「コードが短いから」だけじゃない。ブラウザのエンジン(V8など)は、このメソッドが呼ばれたとき、内部的にメモリの再配置を最適化しているんだ。
自分で `+=` を繰り返すと、毎回新しい文字列インスタンスが生成されてメモリを圧迫し、ガベージコレクション(GC)の負荷が高まる。`repeat()` は、あらかじめ必要なメモリを計算してから一気に確保する、いわゆる「バッファリング」に近い挙動をとる。パフォーマンスが重要な描画処理では、この差が塵積で効いてくるんだよ。
—
2. 知っておくべき「例外処理」のルール
仕様書を読み解くと、`repeat()` には明確な境界条件がある。現場でハマらないために、以下の挙動を頭に入れておいてくれ。
- 0を指定した場合: 空文字 `””` が返る。これは非常に直感的だ。
- 負の数を指定した場合: `RangeError` がスローされる。ここが重要だ。動的に回数を計算している場合、意図せずマイナス値が混入するとアプリが落ちる可能性がある。
- Infinityを指定した場合: これも `RangeError` になる。無限回数繰り返すなんてメモリがいくらあっても足りないから、ブラウザが先回りして防いでくれるわけだ。
これらを踏まえた、実務レベルで「安全に」使うためのラッパーパターンがこれだ。
/
- 安全に文字列を繰り返すユーティリティ
- 負の数やInfinityによるクラッシュを防ぐ
/
function safeRepeat(str, count) {
// 数値化してバリデーション
const n = Math.floor(count);
if (n < 0 || n === Infinity) { console.warn(`無効なリピート回数です: ${count}`); return ''; // または適宜エラーハンドリングを行う } return str.repeat(n); } console.log(safeRepeat('★', 5)); // "★★★★★" console.log(safeRepeat('★', -1)); // 警告が出て空文字が返る ---
3. 実践:現場で使えるUI構築のヒント
`repeat()` は、UIの装飾やデバッグツールで非常に輝く。例えば、パスワードの隠蔽表示や、動的なグリッドの生成などだ。
// パスワードのマスク表示を1行で書く
const password = “mySecretPassword”;
const masked = “●”.repeat(password.length);
console.log(masked); // “●●●●●●●●●●●●●●●●”
// ログ出力の区切り線(デバッグ時に重宝する)
const debugLog = (msg) => {
const line = “-“.repeat(20);
console.log(`${line}\n${msg}\n${line}`);
};
debugLog(“API通信完了”);
—
最後に:シニアからのアドバイス
「たかが文字列の繰り返し」と侮るなかれ。フロントエンドのパフォーマンスは、こうした小さなメソッドの積み重ねで決まる。
もし後輩が `for` ループで文字列を繋げているのを見かけたら、こう伝えてあげてほしい。「そのコード、`repeat()` で書けばメモリ効率も可読性も上がるよ」と。
コードは「動けばいい」ものから、「いかに美しく、かつブラウザに優しいか」を考える段階へ。その意識が、君を一段上のエンジニアへと引き上げるはずだ。また何かあればいつでも聞いてくれ。現場からは以上だ。

コメント