9

構造化クローン アルゴリズムは、とりわけ、 を介してウィンドウ間でデータを渡すために使用されるシリアライゼーション アルゴリズムwindow.postMessageです。(JSON とは異なり) 再帰オブジェクトをサポートしますが、DOM ノード、関数、エラーなどはサポートしません。

私が望むのは、特定のオブジェクトが構造化されたクローン アルゴリズムによってシリアル化できるかどうかを確認する簡単な方法です。オブジェクトを再帰的にウォークし、各プロパティが DOM Node、Function、または Error であるかどうかを確認できますが、それは完全な答えではなく、もっと良い方法があるかどうか疑問に思っていました。

4

1 に答える 1

5

仕様から、私はそれが次のようなものになると思います

function canBeCloned(val) {
  if(Object(val) !== val) // Primitive value
    return true;
  switch({}.toString.call(val).slice(8,-1)) { // Class
    case 'Boolean':     case 'Number':      case 'String':      case 'Date':
    case 'RegExp':      case 'Blob':        case 'FileList':
    case 'ImageData':   case 'ImageBitmap': case 'ArrayBuffer':
      return true;
    case 'Array':       case 'Object':
      return Object.keys(val).every(prop => canBeCloned(val[prop]));
    case 'Map':
      return [...val.keys()].every(canBeCloned)
          && [...val.values()].every(canBeCloned);
    case 'Set':
      return [...val.keys()].every(canBeCloned);
    default:
      return false;
  }
}

これにはいくつかの制限があることに注意してください。

  • オブジェクトに [[DataView]] 内部スロットがあるかどうかを確認できません
  • {}.toString[[Class]] を取得する信頼できる方法ではありませんが、唯一の方法です。
  • 他の仕様は、追加の種類のオブジェクトを複製する方法を定義する場合があります

したがって、アルゴリズムを実行して、エラーが発生するかどうかを確認する方が信頼性が高い場合があります。

function canBeCloned(val) {
  try {
    window.postMessage(val,'*');
  } catch(err) {
    return false;
  }
  return true;
}

messageイベントリスナーがある場合は、それが呼び出されることに注意してください。これを回避したい場合は、値を別のウィンドウに送信してください。たとえば、iframe を使用して作成できます。

var canBeCloned = (function() {
  var iframe = document.createElement('iframe');
  document.body.appendChild(iframe);
  var win = iframe.contentWindow;
  document.body.removeChild(iframe);
  return function(val) {
    try { win.postMessage(val, '*'); }
    catch(err) { return false; }
    return true;
  };
})();
于 2015-09-19T22:39:56.747 に答える