23

我正在寻找一种解决方案来跨浏览器将 Javascript 对象序列化(和反序列化)为字符串,包括恰好是函数的对象成员。一个典型的对象将如下所示:

{
   color: 'red',
   doSomething: function (arg) {
        alert('Do someting called with ' + arg);
   }
}

doSomething() 将仅包含局部变量(无需同时序列化调用上下文!)。

JSON.stringify() 将忽略 'doSomething' 成员,因为它是一个函数。我知道 toSource() 方法会做我想要的,但它是 FF 特定的。

4

5 回答 5

12

您可以使用JSON.stringify类似replacer

JSON.stringify({
   color: 'red',
   doSomething: function (arg) {
        alert('Do someting called with ' + arg);
   }
}, function(key, val) {
        return (typeof val === 'function') ? '' + val : val;
});
于 2014-12-02T18:37:07.363 回答
8

一种快速而肮脏的方式是这样的:

Object.prototype.toJSON = function() {
  var sobj = {}, i;
  for (i in this) 
    if (this.hasOwnProperty(i))
      sobj[i] = typeof this[i] == 'function' ?
        this[i].toString() : this[i];

 return sobj;

};

for in显然,这会影响代码中每个对象的序列化,并且可能会使用未过滤的循环使 naive 代码绊倒。“正确”的方法是编写一个递归函数,将toJSON函数添加到任何给定对象的所有后代成员上,处理循环引用等。然而,假设单线程 Javascript(没有 Web Workers),这个方法应该可以工作并且不会产生任何意外的副作用。

必须将类似的函数添加到 Array 的原型中,以通过返回数组而不是对象来覆盖 Object 的。另一种选择是附加一个,让它根据对象自身的性质有选择地返回一个数组或一个对象,但它可能会更慢。

function JSONstringifyWithFuncs(obj) {
  Object.prototype.toJSON = function() {
    var sobj = {}, i;
    for (i in this) 
      if (this.hasOwnProperty(i))
        sobj[i] = typeof this[i] == 'function' ?
          this[i].toString() : this[i];

    return sobj;
  };
  Array.prototype.toJSON = function() {
      var sarr = [], i;
      for (i = 0 ; i < this.length; i++) 
          sarr.push(typeof this[i] == 'function' ? this[i].toString() : this[i]);

      return sarr;
  };

  var str = JSON.stringify(obj);

  delete Object.prototype.toJSON;
  delete Array.prototype.toJSON;

  return str;
}

http://jsbin.com/yermateno/2/edit

于 2010-09-10T15:19:27.457 回答
1

像这样的东西...

(function(o) {
    var s = "";
    for (var x in o) {
        s += x + ": " + o[x] + "\n";
    }
    return s;
})(obj)

注意:这是一个表达式。它返回作为参数传入的对象的字符串表示形式(在我的示例中,我将传入名为 obj 的变量中)。

您还可以覆盖对象原型的 toString 方法:

Object.prototype.toString = function() {
    // define what string you want to return when toString is called on objects
}
于 2010-09-10T15:34:59.967 回答
1

没有对象本身的帮助是不可能的。例如,您将如何序列化此表达式的结果?

(功能 () {
  变量 x;
  返回 {
      获取:函数(){返回x;},
      设置:函数(y){返回x = y;}
    };
})();

如果你只是取函数的文本,那么当你反序列化时,x将引用全局变量,而不是一个闭包。此外,如果您的函数在浏览器状态下关闭(例如对 div 的引用),您必须考虑您想要它的含义。

当然,您可以编写自己的特定于单个对象的方法,这些方法对您希望引用其他对象具有的语义进行编码。

于 2010-09-17T17:34:00.643 回答
1

JSONfn 插件正是您正在寻找的。

http://www.eslinstructor.net/jsonfn/

——瓦迪姆

于 2013-08-01T01:26:26.090 回答