2012-06-18 3 views
1

JSON.stringifyJSON.parse을 사용하여 객체를 직렬화 및 비 직렬화하는 것은 날짜 객체가 문자열로 직렬화 된 다음 날짜 객체가 아닌 문자열로 다른 측면에서 나오는 것과 같은 미묘한 문제가 있습니다. 대신 postMessage을 사용하여 1 : 1 결과를 얻을 수있는 이점이 있지만 다른 핸들러 처마가 메시지를 떨어 뜨릴까 봐 걱정됩니다. 나 자신의 serializer/deserializer를 작성하는 것을 고려했지만 기본 브라우저 기능을 선호합니다.postMessage를 메시지 시리얼 화기로 사용하는 방법은 무엇입니까?

도청에 대해 걱정할 필요없이 시리얼 라이저처럼 postMessage을 사용할 방법이 있습니까?

참고 : 개발자 도구를 사용하여 도청에 신경 쓰지 않습니다. 내 앱이 모듈과 같은 플러그인을로드하고 있으며 다른 모듈을위한 메시지를 도청 할 수 없도록하고 싶습니다.

+0

질문이 꽤 오래되었습니다. 만약 당신이 정말로 연재 부분에만 관심이 있다면, 제목을 바꾸고 질문의 시체를 줄이는 것을 고려해보십시오. 그러면 다른 사람들 (Google 직원)이 Q & A가 자신의 사례를 설명하는지 여부를 쉽게 판단 할 수 있습니다. –

+0

완료, 질문을 개선하는 희망. 의견을 보내 주셔서 감사합니다! –

답변

4

당신은 JSON.stringifyJSON.parse에 사용자 정의 JSON 파서/stringifier를 제공 할 수 있습니다 : 사용자 정의 자극성 외에도, 당신은 또한 직렬화 될 것입니다 개체에 toJSON 방법을 정의 할 수 있습니다

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

. 이 메서드는 하나의 인수를받습니다. 배열에있는 키의 이름은 이고 적용되는 경우 객체의 속성 이름은입니다. http://jsperf.com/json-reviver :

// 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 비교입니다. 특별한 일을하지 않는 커스텀 리버브는 2 배 느리고 비싼 기능을 가진 리버 버는 훨씬 느리다는 것을 알 수 있습니다.
그러나 마지막 메서드를 기본 JSON과 "수동 변환"을 사용하는 약한 메서드와 비교하면 차이점이 무시 된 것 같습니다.
참고 : 단일 값만 벤치마킹됩니다. 모든 가능한 경우를 나타내는 하나의 벤치 마크를 작성하는 것은 불가능하기 때문에 자신의 (특정) 사례에 대한 맞춤 벤치 마크를 작성하십시오.

나는 .toJSON의 영향을 확인하는 JSPerf test case을 만들었습니다. 노이즈를 분리하기 위해 Date 개체를 기반으로 테스트 사례를 만들었습니다. 여러 함수 호출을 사용하는 사용자 정의 함수는 기본 Date.prototype.toJSON보다 2 배 정도 느립니다.

+0

JSON에 대한 MDN 문서를 읽지 않은 적이 있습니다 그래서 두 번째 매개 변수에 대해 전혀 알지 못했습니다. 감사. =) –

+0

나는 문서에서 이것들을 놓쳤다. 분명히 나는 ​​감추고 있었다. 성능면에서 약간 걱정 되긴하지만 이것은 충분히 좋을 수도 있습니다. 그것에 대한 당신의 생각을 듣고 싶습니다. –

+0

@macke 사용자 정의 replacer, reviver 및 'MyObject.prototype.toJSON' + 두 가지 벤치 마크의 예제를 추가했습니다. –

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를 사용하지 않으려면, 당신은 자신에게이 이벤트 객체의 stopPropagation 방법을 호출하는 이벤트 핸들러를 취소 할 수 있습니다 정보 수준이

function isArray(obj) { 
    return Object.prototype.toString.call(obj) === '[object Array]': 
} 
+0

좋은 제안이고, 나는 커스텀 루트를 잘 진행할 것입니다. 그러나, 나는 네이티브 브라우저 기능을 선호하므로 먼저 살펴 보겠습니다. –

0

DOM 이벤트와 같은 isArray 기능을 코딩 할 수있다 처리 중입니다. 이벤트 처리기가 페이지의 첫 번째 코드인지 확인한 경우 (기본적으로 스크립트 태그가 페이지의 첫 번째 태그인지 확인) stopPropagation을 호출하여 다른 코드가 메시지를 도청하지 못하게 할 수 있습니다. 또한 선택적으로 이벤트를 필터링하여 이벤트 만 필터링 할 수도 있습니다.

그래서 기본적으로이 일을하고있을 것입니다 : 사람들은 여전히 ​​이벤트를 가로 챌 수 Greasemonkey와 같은 도구를 사용할 수 있지만 것을

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

참고. 웹에서는 결코 확신 할 수 없습니다. JavaScript는 오픈 소스 언어입니다. 희망이 비록 도움이됩니다.

+0

이것은 지금까지 해왔지만, 불행하게도 핸들러가 추가되는 순서를 보장 할 수는 없습니다. 비록 내가 그렇다고하더라도, 스펙이 핸들러가 해고되는 순서를 실제로 보장하지 않는다고 생각하기 때문에 어떤 순서로 추가되었는지는 중요하지 않습니다. 대부분의 (모든?) 브라우저는 핸들러를 추가 한 순서대로 실행하므로 실제로는 중요하지 않습니다. 하지만 차라리 더 안정적인 솔루션을 찾고 싶습니다. –

+0

[spec] (http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-basic)에서 : "EventTarget의 모든 EventListener가 트리거 될 수 있지만 해당 EventTarget에 의해 수신 된 모든 이벤트에 대해 EventTarget의 다른 EventListener와 관련하여 이벤트를 수신하는 순서에 대한 지정이 없습니다. " –

관련 문제