1分でわかるJavaScriptで絵文字の文字数をカウントする方法

絵文字の文字数カウント問題

絵文字は通常の文字とは異なり、JavaScriptで文字数をカウントする際には注意が必要です。

例えば、シンプルな方法である「'🤦🏻‍♂️'.length」を使っても、この絵文字の文字数は1ではなく7となり、正確にカウントできません。

'🤦🏻‍♂️'.length // 7

絵文字はサロゲートペアを組み合わせて作られている場合があります。

そのため、.lengthを使うと7文字のように2文字以上で判定されます。

【補足説明】
🤦 (U+1F926) - サロゲートペアとして2ユニット
🏻 (U+1F3FB) - サロゲートペアとして2ユニット
‍[特殊文字] (U+200D) - 1ユニット
♂ (U+2642) - 1ユニット
︎[特殊文字] (U+FE0F) - 1ユニット
これらを合計すると、🤦🏻‍♂️の絵文字は合計7ユニットとしてカウントされます。
したがって、JavaScriptで '🤦🏻‍♂️'.length を実行すると、結果は7になります。

絵文字を正確にカウントするには「emoji-regexライブラリ」または「Intl.Segmenter」を使用します。

emoji-regexライブラリのカウント方法

まず、以下のコマンドでemoji-regexをインストールします。

npm i -D emoji-regex

インストールしたらimportで読み込んで、replaceで絵文字をXに置換後に文字列をカウントします。

import emojiRegex from 'emoji-regex'

const text = '🤦🏻‍♂️TEST🤦🏻'
const replaceText = text.replace(emojiRegex(), 'X')
console.log(replaceText.length) // 6

Intl.Segmenterのカウント方法

Intl.Segmenterで「granularity: "word"」を指定して各文字を1文字として処理できるようにします。

const text = '🤦🏻‍♂️TEST🤦🏻'
const segmeter = new Intl.Segmenter('ja-JP', { granularity: 'word'})
const result = text.map((t) => [...segmeter.segment(t)]).length
console.log(result) // 6

Intl.Segmenterのほうが、emoji-regexのnpm installが不要なので簡単に実装できますが、Firefoxで使えないというデメリットがあります。

そのため、Firefoxを対象とする場合はIntl.Segmenterの使用は避けたほうが良いです。