structured clone algorithm是一種序列化算法,用於在窗口之間通過window.postMessage
傳遞數據。它支持遞歸對象(不像JSON),但不包括DOM節點,函數和錯誤等其他東西。如何檢查一個對象是否可以通過結構化克隆算法進行克隆
我想要的是一種簡單的方法來檢查給定對象是否可以通過結構化克隆算法進行序列化。我可以遞歸地遍歷對象,並檢查每個屬性是否是DOM節點,函數或錯誤,但這不是一個完整的答案,我想知道是否有更好的方法。
structured clone algorithm是一種序列化算法,用於在窗口之間通過window.postMessage
傳遞數據。它支持遞歸對象(不像JSON),但不包括DOM節點,函數和錯誤等其他東西。如何檢查一個對象是否可以通過結構化克隆算法進行克隆
我想要的是一種簡單的方法來檢查給定對象是否可以通過結構化克隆算法進行序列化。我可以遞歸地遍歷對象,並檢查每個屬性是否是DOM節點,函數或錯誤,但這不是一個完整的答案,我想知道是否有更好的方法。
從spec,我認爲這會是這樣的
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;
}
}
注意這有一定的侷限性:
{}.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;
};
})();
我不認爲'|| val instanceof Object'做你想做的事 – Bergi
@Bergi真的,大多數主機對象在原型鏈中都有'Object.prototype'。規範說「如果輸入是一個Object對象*,不知道這是否意味着[[Prototype]]必須完全是'Object.prototype',或者[[Class]]'」Object「' – Oriol
是的, [spec](http://www.w3.org/html/wg/drafts/html/master/infrastructure.html#safe-passing-of-structured-data)提到(在條件列表下面)他們的意思是'[[class]]' – Bergi
爲什麼不試試,再搭上了'DATA_CLONE_ERR'例外,它拋出,如果它不是有效?如果您捕獲到異常,則該對象不可序列化,否則就是。 –
根據上下文,API並不總是使用'window.postMessage',但爲了一致性,如果數據與結構化克隆算法不兼容,我希望它報告錯誤。 – Retsam
Try/catch在這種情況下也應該正常工作。 –