【実務・中級編】 スプレッド構文による文字列の配列変換 – JavaScript実践ガイド

JavaScriptの文字列操作、その「裏側」を理解してサロゲートペアの罠を回避する

やあ。現場でコードを書いていると、「文字列を配列に変換したい」なんて場面には頻繁に出くわすよね。`split(”)` を使って、「よし、これで文字の配列になった」と安心している君。ちょっと待ってほしい。その実装、特定の条件下で爆弾を抱えている可能性がある。

今日は、フロントエンドの現場で「なぜかUIが崩れる」「絵文字が化ける」というバグを撲滅するための、文字列とスプレッド構文の正しい付き合い方について話そう。

—

1. なぜ `split(”)` は時代遅れなのか?

かつての僕たちもよく使っていた `str.split(”)`。これ、実はUnicodeの仕様である「サロゲートペア」を全く考慮していないんだ。

サロゲートペアとは、平たく言えば「2つのコードユニットで1つの文字を表現する」仕組みのこと。絵文字(🍎など)や一部の漢字がこれに該当する。`split(”)` を使うと、この「1つの文字」を無理やり真っ二つに引き裂いてしまう。結果、ブラウザには「表示できない謎の記号」が並ぶことになるわけだ。

2. スプレッド構文 `[…]` の魔法

そこで登場するのが、ES6で導入されたスプレッド構文だ。
文字列に対して `[…str]` と記述するだけで、配列に展開できるのは知っていると思う。だが、この挙動には単なる「便利機能」以上の深い仕様が隠されている。

スプレッド構文は、内部で「イテレータ(Iterator)」を呼び出している。

JavaScriptの文字列イテレータは、Unicodeの符号位置(Code Point)を正しく認識するように設計されている。つまり、サロゲートペアを「1つの文字」として正しく解釈し、配列の要素に格納してくれるんだ。

実践:サロゲートペアを安全に扱うコード

以下のコードを自分の環境で試してみてほしい。`split(”)` と `[…str]` の圧倒的な違いがひと目でわかるはずだ。

const emojiString = ‘🍎🍏🍇’; // 絵文字の文字列

// 1. 古いやり方: split(”)
const splitResult = emojiString.split(”);
console.log(splitResult);
// 出力: [“\uD83C”, “\uDF4E”, “\uD83C”, “\uDF4F”, “\uD83C”, “\uDF47”]
// 惨状:1つの絵文字が2つに分割され、意味をなさない配列になっている

// 2. モダンなやり方: スプレッド構文
const spreadResult = […emojiString];
console.log(spreadResult);
// 出力: [“🍎”, “🍏”, “🍇”]
// 完璧:サロゲートペアを正しく「1文字」として扱えている

3. なぜこれが現場で重要なのか?

「別に絵文字を分割することなんてないよ」と思うかもしれない。しかし、実務においてこの知識は以下のような場面で命を救う。

  • 文字数制限の実装: `textarea` の文字数カウントを実装する際、`length` プロパティを使うと、サロゲートペアが含まれるだけでカウントが狂う。`[…str].length` を使うだけで、ユーザーが直感的に感じる「文字数」と一致させることができる。
  • テキストの反転処理: 文字列を逆順にする際も、スプレッド構文を使わないとサロゲートペアが壊れて表示不能になる。

実用的なユーティリティ例

現場でよく使う「安全な文字数カウント関数」を置いておくよ。

/

  • サロゲートペアを考慮した安全な文字列長取得
  • @param {string} str
  • @returns {number}

/
const getSafeLength = (str) => {
if (typeof str !== ‘string’) return 0;
// スプレッド構文で展開してから長さを測る
return […str].length;
};

// 使用例
console.log(getSafeLength(‘あいうえお’)); // 5
console.log(getSafeLength(‘🍎🍎🍎’)); // 3 (splitだと6になってしまう)

4. チーフアーキテクトからのアドバイス

JavaScriptの仕様は、泥臭い後方互換性の歴史の上に成り立っている。`split(”)` がダメなのは、それが「バイト単位(あるいはコードユニット単位)」で処理する低レイヤーな挙動だからだ。

一方で、スプレッド構文や `Array.from()` は、ECMAScriptの仕様レベルで「イテレータを介して文字の境界を正しく判定する」という、より人間側の解釈に近い動作をする。

結論として:
現代のフロントエンド開発において、文字列を配列に変換する際は、迷わずスプレッド構文 `[…str]` を選ぶこと。これが今の「標準」であり、バグを未然に防ぐための賢い選択だ。

技術は常にアップデートされる。公式ドキュメントを読むのもいいが、こうして「なぜそうなるのか」という裏側のロジックを知っておくと、どんな複雑なUI実装にも動じない自信がつくはずだよ。

また何か気になったら聞いてくれ。現場の知見をいくらでも共有するからさ。頑張って!

コメント

タイトルとURLをコピーしました