如何使用postMessage作为消息序列化器?

Mar*_*ade 2 javascript serialization

使用JSON.stringifyJSON.parse序列化和反序列化对象有一些微妙的问题,例如日期对象被序列化为字符串,然后在另一侧作为字符串而不是日期对象出现.我尝试使用postMessage而不是产生1:1结果的好处,但我担心其他处理程序的eaves会丢弃消息.我考虑过编写自己的序列化器/解串器,但更喜欢本机浏览器功能.

有没有办法postMessage像序列化器一样使用,而不必担心窃听?

注意:我不关心使用开发工具进行窃听.我的应用程序正在加载类似模块的插件,我想确保那些无法窃听其他模块的消息.

Rob*_*b W 6

您可以为JSON.stringify和提供自定义JSON解析器/字符串JSON.parse:

var serialized = JSON.stringify(obj, /*func*/replacer);
var deserialized = JSON.parse(serialized, /*func*/reviver);
Run Code Online (Sandbox Code Playgroud)

除了自定义reviver之外,您还可以toJSON在要序列化的对象上定义方法.此方法接收一个参数:数组中键的名称索引,对象中的属性名称(如果适用).

// Examples of a serializing a function
var dummyFunction = function() {return 'hey';};

Function.prototype.toJSON = function(key) {
    'use strict';
    return this.toString();
};
JSON.stringify(dummyFunction);
// Method 2:
var replacer = function(/*string*/key, /*any*/value, /*boolean*/pretty_print) {
    if (typeof value == 'function') return value.toString();
    return value;
};
JSON.stringify(dummyFunction, replacer);
// >>> "function () {\n    return \"hey\";\n}"
// Result of the previous, stored in a variable
var result =  '"function () {\\n    return \\"hey\\";\\n}"';

// Reviver example
// Note: Just an example. Do not use it without modification in production code,
// Because the pattern can easily be misguided: "function(){}alert('Evil');x={}"
// Even if you do not mind, at least add a try-catch block inside
//   `if (func)`, so that a malformed function does not break the reviver
JSON.parse(result, function(/*string*/key, /*string*/value) {
    var func = /^\s*function\s*\(([^)]*)\)\s\{([\S\s]*)}$/.exec(value);
    if (func) {
        // Note: Function( .. ) is equivalent to new Function( .. )
        var args = func[1].match(/[^,\s]+/g); // <-- Parameters
        // Function body:
        if (args === null) args = [func[2]];
        else args.unshift(func[2]);
        return Function.apply(null, args);
    }
    return value;
});
Run Code Online (Sandbox Code Playgroud)

这是一个JSPerf比较本机解析与解析与reviver:http: //jsperf.com/json-reviver .它表明,一个没有特殊功能的自定义复活器速度慢了两倍,并且具有昂贵功能的复活器速度明显变慢.
但是,当将最后一个方法与使用原生JSON和"手动转换"的较弱方法进行比较时,差异似乎被忽略了.
注意:仅对单个值进行基准测试.确保为您自己的(特定)案例创建自定义基准,因为无法创建一个代表每种可能案例的基准.

我创建了一个JSPerf测试用例来检查其影响.toJSON.为了隔离噪声,我创建了一个基于Date对象的测试用例.具有多个函数调用的自定义函数只比原生函数慢两倍Date.prototype.toJSON.