Javascript:字符串化对象(包括类型函数的成员)

问题描述 投票:0回答:6

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

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

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

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

javascript json function serialization stringify
6个回答
14
投票

您可以将

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

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
循环使 niave 代码出错。 “正确”的方法是编写一个递归函数,在任何给定对象的所有后代成员上添加
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/yerumateno/2/edit


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
}

1
投票

如果没有物体本身的帮助,这是不可能的。例如,您将如何序列化该表达式的结果?

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

如果您只获取函数的文本,那么当您反序列化时,

x
将引用全局变量,而不是闭包中的变量。另外,如果您的函数在浏览器状态下关闭(例如对 div 的引用),您必须考虑您想要它的含义。

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


1
投票

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

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

--瓦迪姆


0
投票

通过 JSON.stringify() 中的 replacer-argument 完美字符串化对象中的函数。 坏处是它在返回值两边加上了撇号。当值是函数时,撇号不可能知道从哪里删除;就像 {"doSomething": "function(arg){...}"}。相反,返回一个 PLACEHOLDER,稍后由该值替换。

var myObj = { color: 'red', doSomething: function (arg) { alert('Do someting called with ' + arg); } } var placeholder = '____PLACEHOLDER____'; var fns = []; var json = JSON.stringify(myObj, function(key, value) { if (typeof value === 'function') { fns.push(value); return placeholder; } return value; }, 2); json = json.replace(new RegExp('"' + placeholder + '"', 'g'), function(_) { return fns.shift(); }); console.log(json)

https://gist.github.com/cowboy/3749767

© www.soinside.com 2019 - 2024. All rights reserved.