2

JSON.stringifyとを使用しJSON.parseてオブジェクトをシリアル化および逆シリアル化すると、日付オブジェクトが文字列としてシリアル化され、日付オブジェクトではなく文字列として出力されるなどの微妙な問題があります。代わりに、1:1 の結果を生成するという利点があるものを使用してみましpostMessageたが、他のハンドラーがメッセージをひさしで落としてしまうのではないかと心配しています。独自のシリアライザー/デシリアライザーを作成することを検討しましたが、ネイティブのブラウザー機能を好むでしょう。

postMessage盗聴を気にせずに、シリアライザーのように使う方法はありますか?

注: 開発ツールを使用した盗聴については気にしません。私のアプリはモジュールのようなプラグインをロードしていますが、それらが他のモジュール向けのメッセージを盗聴できないようにしたいと考えています。

4

3 に答える 3

6

カスタム JSON パーサー/文字列化子をJSON.stringifyおよびに提供できJSON.parseます。

var serialized = JSON.stringify(obj, /*func*/replacer);
var deserialized = JSON.parse(serialized, /*func*/reviver);

カスタム リバイバーに加えて、toJSONシリアル化されるオブジェクトにメソッドを定義することもできます。このメソッドは引数を 1 つ受け取ります。配列内のキーの名前のインデックス、オブジェクト内のプロパティ名 (該当する場合) です。

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

ネイティブ解析とリバイバーを使用した解析の JSPerf 比較を次に示します: http://jsperf.com/json-reviver。特別なことを何もしないカスタム リバイバーは 2 倍遅く、高価な機能を備えたリバイバーは大幅に遅いことがわかります。
ただし、最後の方法を、ネイティブ JSON と「手動変換」を使用するより弱い方法と比較すると、違いは無視されているように見えます。
注: 単一の値のみがベンチマークされます。可能性のあるすべてのケースを表す 1 つのベンチマークを作成することは不可能であるため、独自の (特定の) ケース用のカスタム ベンチマークを必ず作成してください。

の影響をチェックするJSPerf テスト ケースを作成しました.toJSONDateノイズを分離するために、オブジェクトに基づいてテスト ケースを作成しました。複数の関数呼び出しを持つカスタム関数は、ネイティブ関数よりもわずか 2 倍遅くなりますDate.prototype.toJSON

于 2012-06-18T15:40:44.690 に答える
1

を使用する代わりにpostMessage、特定のクローン作成方法を使用できます。

私はこれを使用します:

function goclone(source) {
    if ($.isArray(source)) {
        var clone = [];
        for (var i=0; i<source.length; i++) {
            if (source[i]) clone[i] = goclone(source[i]);
        }
        return clone;
    } else if (typeof(source)=="object") {
        var clone = {};
        for (var prop in source) {
            if (source[prop]) {
                clone[prop] = goclone(source[prop]);
            }
        }
        return clone;
    } else {
        return source;
    }
}

プロトタイプ、関数などはコピーせず、null/NaNフィールドを無視します。

jquery を使用したくない場合は、次のisArrayような関数を自分でコーディングできます。

function isArray(obj) {
   return Object.prototype.toString.call(obj) === '[object Array]':
}
于 2012-06-18T15:34:26.063 に答える
1

stopPropagationDOM イベント レベル 2 は、処理しているイベント オブジェクトのメソッドを呼び出す任意のイベント ハンドラーによって取り消すことができます。イベント ハンドラーがページの最初のハンドラーであることを確認する場合 (基本的には、スクリプト タグがページの最初のタグであることを確認することによって) を呼び出しstopPropagationて、他のコードがメッセージを盗聴するのを防ぐことができます。また、これを選択的に行って、イベントのみが除外されるようにすることもできます。

したがって、基本的にこれを行うことになります:

window.addEventListener("message", function (event) {
    var data = JSON.parse(event.data);

    if (data.secret === "my event and not anyone else's") {
        // do something
        event.stopPropagation();
    }
}, false);

ただし、gracemonkey などのツールを使用してイベントを傍受できることに注意してください。ウェブ上では、決して確信が持てません。JavaScript はオープンソース言語です。これが役立つことを願っています。

于 2012-06-18T15:40:06.063 に答える