k1mu0419
@k1mu0419 (Yoshito Kimura)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

特定のケースのみ、正規表現(?<=)を使ったJavaScriptの「split()」メソッドが原因でReferenceErrorになってしまう?

解決したいこと

特定のブラウザから閲覧したケースのみ

ReferenceError : Can't find variable:関数名();

エラーが発生する状況。

エラーが起こった状況

このウェブアプリ「読みやすさチェッカー」↓を開発中に発生したエラーです。

まず、アプリはWindowsとMacのGoogleChromeとFirefoxから使用する場合は問題なく動きます。
しかし、MacのSafariや、iPnoneやiPadのSafariとGoogleChromeから使用すると、JavaScriptの関数が動きませんでした。

MacのSafariのデベロッパツールで確認すると、コンソールに

ReferenceError : Can't find variable:関数名();

とのエラーが発生していました。

自分で試したこと

まず、自分なりに「ReferenceError : Can't find variable」で調べてみると、
「ブラウザのバージョンが古いのではないか」との結果が出てきました。

しかし、調べてみてもSafariは古いバージョンではありませんでした。
 
 
 
次に、具体的な原因を調べるためにJavaScriptのファイルを少しずつコメントアウトして比較していきました。

すると、次の2行がエラーの発生源だと分かりました。

index.js
    Sentence = text.split(/(?<=。)|(?<=.)|(?<=!)|(?<=?)|(?<=<br \/>)/);
    NoSpaceSentence = text.split(/(?<=。)|(?<=.)|(?<=!)|(?<=?)|(?<=<br \/>)/);

このアプリでは、文章をテキストを読点や改行で分けるために、JavaScriptの「split()」メソッドを使いました。

しかし、アプリの性質上テキストをただ分割するのではく、
読点や改行を残したいので正規表現(?<=)を使って区切り文字を直前の要素に含めています。

 
この部分の記述を

index.js
    Sentence = text.split(/。|.|!|?|<br \/>/);
    NoSpaceSentence = text.split(/。|.|!|?|<br \/>/);

こう書き換えると、MacのSafariや、iPnoneやiPadのSafariとGoogleChromeから使用してもエラーは発生しなくなりました。

ただ、これでは分割したテキストから"区切り文字に設定している読点や改行"まで消えるので、やりたい処理はちゃんとできません。

現在の状態

WindowsとMacのGoogleChromeとFirefoxからは問題なく動くので、
元々の正規表現(?<=)を使ったプログラムを実行するページと、
機能は不完全ながらエラーが出ないページの2つ用意しています。

したがって、もしも

ReferenceError : Can't find variable:関数名();

でJavaScriptが上手く動かない場合は、エラーが出ないページへの誘導↓が表示されます。

ScreenShot-720213818318.png

付け焼き刃感は否めません…。

ぜひ、知恵を貸していただきたいです。よろしくお願いいたします。

回答ありがとうございました!!

一晩のうちにいくつもの解決策を教えていただき、どのやり方も(?<=)を使わずに処理ができました。
とても助かり、勉強になりました。ありがとうございます。

0

3Answer

splitではなくmatchを使えば(?<=)を使わず同等の分割ができるかと思いますがどうでしょうか。

Sentence = text.match(/.+?(。|.|!|?|<br \/>|$)/sg);
3Like

Comments

  1. @k1mu0419

    Questioner

    回答ありがとうございます!
    matchメソッドにはこんな使い方もできるのですね…!勉強になりました。

Safari は最新バージョンでも正規表現の後読み (?<=) に対応していません。

やりたい処理を後読みを使わずに実現するには、置換で各区切り文字の後ろに NUL 文字1を挿入してから NUL 文字で分割するといいでしょう。

Sentence = text.replace(/(。|.|!|?|<br \/>)/, '$1\x00').split('\x00');
  1. 対象のテキスト中に現れない文字(列)であればなんでもいいです。

1Like

Comments

  1. @k1mu0419

    Questioner

    回答ありがとうございます!
    Safari の最新バージョンでも対応してなかったのですね…。
    なるほど…!あえて必要無い文字を入れて区切る方法ですか…全く思いつきませんでした。

キャプチャで文自体でsplit()も方法の1つかと。
※分割される部分が空文字列になるので、下の例はfilter()を使ってます。

text.split(/(.+?(?:。|.|!|?|<br \/>))/).filter(s => s.length > 0);

(余談)<br \/>の代わりに\nではダメなのでしょうか?シンプルに書けると思います……

1Like

Comments

  1. @k1mu0419

    Questioner

    回答ありがとうございます!
    こんな書き方もあるんですね…。
    全く知りませんでした。勉強になります。

    そうですね…他の部分の処理には<br \/>の方が都合が良かったので、こう書いてしまいました。
    もう一度、\nで書けないか見直してみます。

Your answer might help someone💌