JavaScriptのString.isWellFormedメソッド:古いバージョンでも安心な代替方法とは?


孤立サロゲートとは、Unicode 文字を表現するために使用される 2 つの 16 ビット ユニットのうち、1 つだけが使用されている状態を指します。これは、文字列が正しくエンコードされていないことを示し、様々な問題を引き起こす可能性があります。

String.isWellFormed メソッドは、このような問題を回避するために使用できます。このメソッドは、true を返せば文字列が有効な形式であることを示し、false を返せば孤立サロゲートが含まれていることを示します。


const str1 = "正しい文字列";
const str2 = "孤立サロゲートを含む文字列\uD83D";

console.log(str1.isWellFormed()); // true
console.log(str2.isWellFormed()); // false

String.isWellFormed メソッドの使用例

  • 文字列を処理する前に、その文字列が破損していないかどうかを確認する
  • JSON データを解析する前に、そのデータが有効な形式かどうかを確認する
  • エンコードされた URI を作成する前に、その URI が有効な形式かどうかを確認する

注意点

  • このメソッドは、パフォーマンスが非常に優れています。これは、JavaScript エンジンが文字列の内部表現に直接アクセスできるためです。
  • String.isWellFormed メソッドは、ES2015 以降でしか使用できません。古いバージョンの JavaScript では、このメソッドはサポートされていません。

String.isWellFormed メソッドは、JavaScript の String オブジェクトに対して使用されるメソッドで、文字列が有効な形式かどうかをチェックします。このメソッドは、孤立サロゲートと呼ばれる不正な文字列エンコーディングが含まれていないかどうかを判断します。



例 1:エンコードされた URI の作成前に、その URI が有効な形式かどうかを確認する

function encodeURIifWellFormed(uri) {
  if (uri.isWellFormed()) {
    return encodeURI(uri);
  } else {
    console.error(`URI "${uri}" is not well-formed`);
    return null;
  }
}

const uri1 = "https://www.example.com";
const uri2 = "https://www.example.com/path/\uD83D";

console.log(encodeURIifWellFormed(uri1)); // https://www.example.com
console.log(encodeURIifWellFormed(uri2)); // null

例 2:JSON データを解析する前に、そのデータが有効な形式かどうかを確認する

function parseJSONifWellFormed(data) {
  if (data.isWellFormed()) {
    try {
      return JSON.parse(data);
    } catch (error) {
      console.error(`JSON data is not well-formed: ${error.message}`);
      return null;
    }
  } else {
    console.error(`JSON data is not well-formed`);
    return null;
  }
}

const jsonData1 = '{"name": "John Doe", "age": 30}';
const jsonData2 = '{"name": "John Doe", "age": 30}\uD83D';

console.log(parseJSONifWellFormed(jsonData1)); // { name: 'John Doe', age: 30 }
console.log(parseJSONifWellFormed(jsonData2)); // null
function processStringifWellFormed(str) {
  if (str.isWellFormed()) {
    // 文字列を処理する
    console.log(str.toUpperCase());
  } else {
    console.error(`String "${str}" is not well-formed`);
  }
}

const str1 = "Hello, world!";
const str2 = "Hello, world!\uD83D";

processStringifWellFormed(str1); // HELLO, WORLD!
processStringifWellFormed(str2); // String "Hello, world!\uD83D" is not well-formed


そのため、古いバージョンの JavaScript で同様の機能を実現したい場合は、以下の代替方法を検討する必要があります。

正規表現を使用する

正規表現を使用して、孤立サロゲートを含む文字列を検出することができます。以下の正規表現は、この目的に使用できます。

/[\uD800-\uDBFF][^\uDC00-\uDFFF]/

この正規表現を test() メソッドと組み合わせて使用することで、文字列が有効な形式かどうかを確認できます。

function isWellFormed(str) {
  return !/[\uD800-\uDBFF][^\uDC00-\uDFFF]/.test(str);
}

const str1 = "正しい文字列";
const str2 = "孤立サロゲートを含む文字列\uD83D";

console.log(isWellFormed(str1)); // true
console.log(isWellFormed(str2)); // false

String.prototype.codePointAt() メソッドを使用する

String.prototype.codePointAt() メソッドは、指定されたインデックスにおける文字のコードポイントを返します。このメソッドを使用して、各文字のコードポイントが有効な範囲内かどうかを確認することで、孤立サロゲートを検出することができます。

function isWellFormed(str) {
  for (let i = 0; i < str.length; i++) {
    const codePoint = str.codePointAt(i);
    if ((codePoint >= 0xD800 && codePoint <= 0xDBFF) && !str.codePointAt(i + 1)) {
      return false;
    }
  }
  return true;
}

const str1 = "正しい文字列";
const str2 = "孤立サロゲートを含む文字列\uD83D";

console.log(isWellFormed(str1)); // true
console.log(isWellFormed(str2)); // false

ライブラリを使用する

UNICODEWHATWG などのライブラリは、String.isWellFormed メソッドを含む様々なユーティリティを提供しています。これらのライブラリを使用することで、古いバージョンの JavaScript でも String.isWellFormed メソッドと同等の機能を利用することができます。

例:UNICODE ライブラリを使用する

const unicode = require('unicode-8.js');

function isWellFormed(str) {
  return unicode.isWellFormedString(str);
}

const str1 = "正しい文字列";
const str2 = "孤立サロゲートを含む文字列\uD83D";

console.log(isWellFormed(str1)); // true
console.log(isWellFormed(str2)); // false

これらの代替方法は、String.isWellFormed メソッドと同じ機能を提供しますが、パフォーマンスや互換性において若干の違いがある可能性があることに注意する必要があります。

  • 各代替方法には、パフォーマンスや互換性において若干の違いがある可能性があります。
  • 古いバージョンの JavaScript では、正規表現、String.prototype.codePointAt() メソッド、ライブラリなどの代替方法を使用することができます。
  • String.isWellFormed メソッドは ES2015 以降でのみ使用できます。