簡體   English   中英

如何檢查結構化克隆算法是否可以克隆對象

[英]How to check if an object can be cloned by the structured clone algorithm

結構化克隆算法是一種序列化算法,用於通過window.postMessage在窗口之間傳遞數據。 它支持遞歸對象(與JSON不同),但不支持DOM節點,函數和錯誤等

我想要的是一種檢查給定對象是否可以通過結構化克隆算法序列化的簡單方法。 我可以遞歸地遍歷對象並檢查每個屬性是否是DOM節點,函數或錯誤,但這不是一個完整的答案,我想知道是否有更好的方法。

規范來看,我認為它會是這樣的

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;
  };
})();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM