こんにちは。フロントエンドの現場で日々、JavaScriptの非情なメモリリークや、V8エンジンの機嫌と格闘しているチーフアーキテクトの私だ。
さて、今回は多くの開発者が「こんなの`indexOf() !== -1`の糖衣構文(シンタックスシュガー)だろ」とナメてかかりがちな、`String.prototype.includes()`について深掘りしようと思う。
だが、ちょっと待ってほしい。その「なんとなく動く」コードの積み重ねが、大規模なSPA(シングルページアプリケーション)において、ガベージコレクション(GC)のスパイクを引き起こし、フレームドロップの元凶になっているとしたら?
今回は、単なる「含まれているかを真偽値で返すメソッド」という基本のおさらいで終わる気はない。ブラウザエンジンの内部挙動、メモリ効率、そして実務で踏み抜きがちなエッジケースまで、シニアエンジニアが知るべきすべてを語り尽くそう。
—
1. `includes()` の基本と、V8エンジン内部の幻想
まずは基本から。`str.includes(searchString[, position])` は、指定した文字列が含まれているかを `true` か `false` で返す。かつて我々は `indexOf(‘foo’) !== -1` と書いていたものだが、可読性の観点からは圧倒的に優れている。
しかし、ここでエンジニアとしての嗅覚を働かせてほしい。「内部で何が起きているのか?」だ。
ES2015(ES6)でこのメソッドが標準化された際、多くのJavaScriptエンジン(V8、SpiderMonkey、JavaScriptCoreなど)は、文字列のエンコーディング(UTF-16)を考慮した効率的な部分文字列検索アルゴリズム(Boyer-Moore-HorspoolやTwo-Wayアルゴリズムなど)の最適化を施した。
以下のコードを見てほしい。一見、何気ない判定処理だ。
/
- ユーザーの入力値から特定の危険なキーワードを検知する
- @param {string} input – ユーザーからの入力文字列
- @returns {boolean}
/
function containsDangerousKeyword(input) {
// プリミティブな文字列であれば、V8の内部表現(SeqString等)に対して直接高速なスキャンが走る
const blacklist = [‘

コメント