PrototypeJS版本1.6.0.2重写JSON.parse和JSON.stringify并中断socket.io功能

时间:2014-01-20 14:03:02

标签: javascript json node.js socket.io prototypejs

基本上,socket.io使用nativeJSON来包含和解码数据包,我的问题是我不得不使用这个版本的原型来改变JSON行为。当我应该进入服务器时:

socket.on('event', function (a, b, c), 我明白了 socket.on('event', function ([a, b, c], undefined, undefined)

一种解决方案是在json.js上注释这一行:

/* socket.io-client/lib/json.js
if (nativeJSON && nativeJSON.parse){
    return exports.JSON = {
      parse: nativeJSON.parse
    , stringify: nativeJSON.stringify
    };
  }
*/

但这种变化会严重影响绩效。

有没有办法恢复原生JSON功能? 是否可以创建一个隐藏的iframe来克隆JSON对象以恢复旧功能?

2 个答案:

答案 0 :(得分:2)

一种解决方案是杀死Prototype的toJSON()扩展方法:

if(window.Prototype) {
    delete Object.prototype.toJSON;
    delete Array.prototype.toJSON;
    delete Hash.prototype.toJSON;
    delete String.prototype.toJSON;
}

然后你应该能够毫无问题地使用浏览器的原生JSON.parse / stringify方法。

答案 1 :(得分:0)

如果您不想杀死所有内容,并且拥有可在大多数浏览器上使用的代码,您可以这样做:

(function (undefined) { // This is just to limit _json_stringify to this scope and to redefine undefined in case it was
  if (true ||typeof (Prototype) !== 'undefined') {
    // First, ensure we can access the prototype of an object.
    // See http://stackoverflow.com/questions/7662147/how-to-access-object-prototype-in-javascript
    if(typeof (Object.getPrototypeOf) === 'undefined') {
      if(({}).__proto__ === Object.prototype && ([]).__proto__ === Array.prototype) {
        Object.getPrototypeOf = function getPrototypeOf (object) {
          return object.__proto__;
        };
      } else {
        Object.getPrototypeOf = function getPrototypeOf (object) {
          // May break if the constructor has been changed or removed
          return object.constructor ? object.constructor.prototype : undefined;
        }
      }
    }

    var _json_stringify = JSON.stringify; // We save the actual JSON.stringify
    JSON.stringify = function stringify (obj) {
      var obj_prototype = Object.getPrototypeOf(obj),
          old_json = obj_prototype.toJSON, // We save the toJSON of the object
          res = null;
      if (old_json) { // If toJSON exists on the object
        obj_prototype.toJSON = undefined;
      }
      res = _json_stringify.apply(this, arguments);
      if (old_json)
        obj_prototype.toJSON = old_json;
      return res;
    };
  }
}.call(this));

这看起来很复杂,但这只是处理大多数用例的复杂问题。 主要思想是覆盖JSON.stringify从作为参数传递的对象中删除toJSON,然后调用旧的JSON.stringify,最后将其恢复。