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

Posted

技术标签:

【中文标题】Javascript:字符串化对象(包括类型函数的成员)【英文标题】:Javascript: stringify object (including members of type function) 【发布时间】:2011-04-10 18:51:33 【问题描述】:

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


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

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

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

【问题讨论】:

我只是发表评论,因为我没有提供完整的解决方案。可能有帮助的一件事是,您可以通过调用 toString() 来对函数进行字符串化。 jsfiddle.net/HFMaz 不确定是否支持跨浏览器。 这是经常被问到的,但我找不到任何相关的东西:\为什么你仍然需要序列化函数?也许有更好的方法来安排你的代码? 这是所见即所得的项目。每个 Javascript 对象(带有方法)都定义了页面组件的行为。页面内容(包括 JS 行为)必须保存在服务器端,因此需要序列化。 代码是如何创建的?看来您应该可以在流程的早期阶段访问所有这些的字符串表示形式。 我希望这不会被广大公众使用......否则你必须确保我无法 XSS 那个东西。 【参考方案1】:

您可以将JSON.stringifyreplacer 一起使用,例如:

JSON.stringify(
   color: 'red',
   doSomething: function (arg) 
        alert('Do someting called with ' + arg);
   
, function(key, val) 
        return (typeof val === 'function') ? '' + val : val;
);

【讨论】:

我最终使用了JSON.stringify(myObject, function(key, val) return (typeof val === 'function') ? '[function]' : val; , 4);,它的输出非常好。【参考方案2】:

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

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/yerumateno/2/edit

【讨论】:

很好,除了数组不再序列化为数组。 解析函数会是什么样子?所有函数都在字符串中,所以在解析时我们需要将它们转换回函数。【参考方案3】:

这样的……

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

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

你也可以重写 Object 原型的 toString 方法:

Object.prototype.toString = function() 
    // define what string you want to return when toString is called on objects

【讨论】:

【参考方案4】:

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

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

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

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

【讨论】:

【参考方案5】:

JSONfn 插件正是您正在寻找的。​​p>

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

--瓦迪姆

【讨论】:

我已经用我的对象进行了测试,该对象具有功能但无法正常工作。

以上是关于Javascript:字符串化对象(包括类型函数的成员)的主要内容,如果未能解决你的问题,请参考以下文章

Web | JavaScript的引用数据类型强制转换类型

JavaScript的理解记录

什么是JavaScript的原始值?

JavaScript语言精粹

JavaScript基础入门教程

JavaScript中的原型继承