ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript が文字列を分割するときに生成される null 文字の解決策_javascript のヒント

JavaScript が文字列を分割するときに生成される null 文字の解決策_javascript のヒント

WBOY
WBOYオリジナル
2016-05-16 16:35:131618ブラウズ

問題の説明

JavaScript の Split メソッドを使用して文字列を分割するとき、特に区切り文字として正規表現を使用するときに、いくつかの空の文字列 "" が表示されます。

関連する質問

文字列をグループ化するときに Javascript の正規表現で空の文字列グループが生成されますか?

上記の質問で、被験者が正規表現を使用して文字列を分割すると、複数の空の文字列「」が生成されました。コードは次のとおりです。

コードをコピー コードは次のとおりです:

'张sdf四上法asdfwengfenaa33网s'.split(/([u4e00-u9fa5]{1})/gi);
//出力 ["", "张", "sdf", "四", "", "上", "", "法", "asdf", "王", "", "fen", "aa33 "、"网"、"s"]

では、これらの空の文字列の理由は何でしょうか?

問題分析

Google で検索したところ、関連する結果はあまりなく、あっても詳細な説明はあまりありませんでした。簡単に説明した後、ECMAScript 仕様へのリンクを付けました。本当の理由を知りたければ、しっかりと規制を読んでみる必要があるようです。

関連規格

それでは、次に、国際的な慣例に従って、ECMAScript の標準的なタウンホールから始めましょう。

コードをコピーします コードは次のとおりです:

String.prototype.split (区切り文字、制限)

この章では、split メソッドの実行手順を詳しく説明します。興味がある場合は、ステップごとに詳しく説明します。不適切な点がある場合は、ここでは空の文字列の生成に関連する手順のみを説明します。誰でも提案してください。

関連手順

いくつかのステップを抽出します:

プロセス全体の中で最も重要なステップはステップ 13 のサイクルであり、このサイクルで行われる主な内容は次のとおりです:
•p と q の値を定義します。p と q の値は、各ループの先頭では同じです (このステップはループの外にあります)。 •SplitMatch(S, q, R) メソッドを呼び出して文字列を分割します。 •返されたさまざまな結果に従って、さまざまなブランチが実行され、メインブランチはブランチ ⅲ です。 •分岐 ⅲ は、返された結果を事前定義された配列 A に埋めるために 8 つの小さなステップに分割されます
•これらの 8 つの小さなステップでは、ステップ 1 の機能は、元の文字列の部分文字列を返すことです。開始位置は p (含まれません)、終了位置は q (含まれません) です。 注: このステップでは、空の文字列が返されます。生成されます。以下で簡単に参照できるように、切り詰められた文字列としてマークします。
•前のステップの部分文字列を配列 A
に追加します。 •次のいくつかのステップでは、関連する変数を更新し、次のサイクルを続行します。 (手順 7 の機能は、正規表現内のキャプチャ グループを配列 A に保存することであり、空の文字列の生成とは関係ありません)

SplitMatch(S, q, R)

次に、SplitMatch(S, q, R) メソッドが何を行うのかを理解する必要があります。この方法については、分割仕様の後半で説明します。主に行うことは、区切り文字の種類に応じて対応する操作を実行することです:
• 区切り文字が RegExp 型の場合、RegExp の内部メソッド [[Match]] を呼び出して文字列と一致する場合は、失敗が返されます。それ以外の場合は、MatchResult 型の結果が返されます。

・区切り文字が文字列の場合は一致と判断し失敗を返し、成功した場合はMatchResult型の結果を返します。


試合結果

上記の手順では、MatchResult 型の別の変数を導入します。ドキュメントを確認すると、このタイプの変数には endIndex と Captures という 2 つの属性があることがわかりました。endIndex の値は、文字列の一致位置に 1 を加えたものです。区切り文字が正規表現の場合、Captures は配列として理解できます。区切り文字が文字列の場合は空の配列になります。

次へ

上記の手順から、文字列をインターセプトするステップで分割文字列が生成されることがわかります (正規表現のグループ キャプチャを除く)。その機能は、指定された開始位置 (含まれる) と終了位置 (含まれない) の間の文字列をインターセプトすることです。では、いつ "" を返すのでしょうか。開始位置と終了位置の値が等しいという特殊なケースがあります。仕様には文字列をインターセプトするための標準的な手順が示されていないため、これは単なる推測です。

ここまで来たのですから、もう一歩前進してみませんか?

そこで、具体的な実装方法が見つかるかどうかを確認するために、V8 のソース コードを検索してみました。関連するコード、ソースコードリンク

を見つけました。

ここにそのうちの 1 つからの抜粋を示します:


コードをコピー コードは次のとおりです:

function StringSplitJS(区切り文字, リミット) {
...
...
//区切り文字が文字列の場合
if (!IS_REGEXP(区切り文字)) {
var separator_string = TO_STRING_INLINE(区切り文字);

if (limit === 0) return [];

// ECMA-262 は、区切り文字が定義されていない場合、結果は
である必要があると規定しています。 // 文字列全体を含むサイズ 1 の配列であること。
If (IS_UNDEFINED(separator)) return [件名];

var separator_length = separator_string.length;

//区切り文字は空の文字列であり、文字配列が直接返されます
(separator_length === 0) の場合、%StringToArray(subject, limit) を返します。

var result = %StringSplit(件名、区切り文字列、制限);

結果を返します;
}

if (limit === 0) return [];

// 区切り文字が正規表現の場合、StringSplitOnRegExp
を呼び出します Return StringSplitOnRegExp(件名、区切り文字、制限、長さ);
}

//ここでは一部のコードを省略します

コード内で、配列を埋めるときに文字列をインターセプトするために %_SubString メソッドが呼び出されていることがわかりました。見つけた場合は、お知らせください。しかし、JavaScript の部分文字列メソッドに対応する StringSubstring メソッドは、%_SubString メソッドを呼び出して結果を返すことがわかりました。次に、'abc'.substring(1,1) が "" を返す場合、開始位置と終了位置が同じ場合に %_SubString メソッドが "" を返すことを意味します。試してみると結果がわかります。

では、開始位置が終了位置と等しくなるのはいつですか (つまり、q === p)?上記の手順に従って段階的に分析し、最終的に次のことがわかりました。
・元の文字列 S が一度区切り文字と一致すると、次の文字列 S の位置も区切り文字と一致します。例: 'abbbc'.split('b')、'abbbc'.split(/(b){1}/)
•もう 1 つの状況は、文字列の先頭の 1 つまたは複数の文字が区切り文字と一致する場合です。例: 'abc'.split('a')、'abc'.split(/ab/)
•文字列の末尾の 1 つまたは複数の文字列が区切り文字に一致する場合もあり、関連する手順は手順 14 です。
例: 'abc'.split('c')、'abc'.split(/bc/)

さらに、正規表現を区切り文字として使用すると、返される結果に unknown が表示される場合があります。
例: 'abc'.split(/(d)*/)

冒頭の例に戻って、上記の条件を満たしていますか?

余談

ECMAScript の標準仕様をこんなに丁寧に読んだのは初めてで、読む過程は確かに苦痛ですが、理解した後はとても楽しい気持ちになります。この質問を提起し、フォローしてくださった質問者にも感謝します。
ちなみに、正規表現が区切り文字として使用されている場合、グローバル修飾子 g は無視されるため、追加の利点があります。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。