在Internet Explorer中实现Mozilla的toSource()方法

时间:2008-10-05 03:03:41

标签: javascript

是否有人为Internet Explorer和其他非Gecko浏览器实现了Mozilla的Object.toSource()方法?我正在寻找一种将简单对象序列化为字符串的轻量级方法。

8 个答案:

答案 0 :(得分:9)

请考虑以下事项:(使用FireFox 3.6时)

javascript:
  x=function(){alert('caveat compter')};
  alert(['JSON:\t',JSON.stringify(x),'\n\ntoSource():\t',x.toSource()].join(''));

显示:

  

JSON:

     

toSource():( function(){alert(“caveat compter”);})

甚至:

javascript:
x=[];x[3]=x;
alert('toSource():\t'+x.toSource());
alert('JSON can not handle this at all and goes "infinite".');
alert('JSON:\n'+JSON.stringify(x));

显示:

  

toSource():#1 = [,,,#1#]

和“去'无限'”消息跟随JSON的stackoverflow递归离题。

这些示例强调了由toSource()呈现的JSON表示中明确排除的表达式的细微之处。

对于所有情况,组合程序来复制相同的结果并不容易,因为Gecko toSource()原语非常强大。

以下是一些复制toSource()功能的程序必须成功处理的“移动目标”:

javascript:
function render(title,src){ (function(objRA){
    alert([ title, src,
        '\ntoSource():',objRA.toSource(),
        '\nJSON:',JSON.stringify(objRA)     ].join('\n'));
    })(eval(src));
}
render('Simple Raw Object source code:',
    '[new Array, new Object, new Number, new String, ' +
        'new Boolean, new Date, new RegExp, new Function]'  );

render( 'Literal Instances source code:',
    '[ [], 1, true, {}, "", /./, new Date(), function(){} ]'    );

render( 'some predefined entities:',
    '[JSON, Math, null, Infinity, NaN, ' +
        'void(0), Function, Array, Object, undefined]'      );

显示:

    Simple Raw Object source code:
    [new Array, new Object, new Number, new String, 
                new Boolean, new Date, new RegExp, new Function]

    toSource():
    [[], {}, (new Number(0)), (new String("")), 
                (new Boolean(false)), (new Date(1302637995772)), /(?:)/, 
                            (function anonymous() {})]

    JSON:
    [[],{},0,"",false,"2011-04-12T19:53:15.772Z",{},null]

然后显示:

    Literal Instances source code: 
    [ [], 1, true, {}, "", /./, new Date(), function(){} ]

    toSource():  
    [[], 1, true, {}, "", /./, (new Date(1302638514097)), (function () {})]

    JSON:  
    [[],1,true,{},"",{},"2011-04-12T20:01:54.097Z",null]

最后:

    some predefined entities:
    [JSON, Math, null, Infinity, NaN, void(0), 
                        Function, Array, Object, undefined]

    toSource():
    [JSON, Math, null, Infinity, NaN, (void 0), 
        function Function() {[native code]}, function Array() {[native code]}, 
            function Object() {[native code]}, (void 0)]

    JSON:
    [{},{},null,null,null,null,null,null,null,null]

如果需要使用简单的良性人类消费来查看对象的内部结构,那么如果翻译是“要使用”或不那么严格的话,之前的分析就很重要。作为表示,主要JSON功能是在环境之间传输某些结构化信息。

toSource()函数的质量是影响但不限于以下内容的程序的指称语义的一个因素:
往返计算,最小不动点属性和反函数。

  • 重复代码转换 静止到静止状态?
  • obj.toSource()== EVAL(EVAL(EVAL(obj.toSource())。toSource())。toSource())。toSource()?
  • 考虑是否有意义 是否obj == eval(obj.toSource())?
  • 是否撤消转化结果 只是一个类似的对象,但一个 IDENTICAL一个?
    这是一个加载 具有深远影响的问题 克隆操作对象时。

还有很多很多......

请注意,当obj包含已执行的代码对象时,上述问题会更加重要,例如(new Function ...)()!

答案 1 :(得分:5)

如果不符合Firefox的确切序列化格式,则可以使用http://json.org中列出的JavaScript JSON序列化/反序列化库之一。使用像JSON这样的标准方案可能比模仿专有的Gecko格式更好。

答案 2 :(得分:5)

如果需要使用循环引用序列化对象,可以使用https://github.com/douglascrockford/JSON-js上的Douglas Crockford对JSON对象的cycle.js扩展。这非常类似于Source(),虽然它不会序列化函数(但可能适用于使用函数的toString方法)。

答案 3 :(得分:3)

你可以这样做:

Object.prototype.getSource = function() {
    var output = [], temp;
    for (var i in this) {
        if (this.hasOwnProperty(i)) {
            temp = i + ":";
            switch (typeof this[i]) {
                case "object" :
                    temp += this[i].getSource();
                    break;
                case "string" :
                    temp += "\"" + this[i] + "\"";    // add in some code to escape quotes
                    break;
                default :
                    temp += this[i];
            }
            output.push(temp);
        }
    }
    return "{" + output.join() + "}";
}

答案 4 :(得分:1)

为了更进一步:当你发送一些东西 - 要继续工作 - 接收器必须得到它并且能够对它进行处理。因此,下一段代码将完成这一操作 - 改编自Eliran Malka的前一个答案。

// SENDER IS WRAPPING OBJECT TO BE SENT AS STRING
// object to serialize
var s1 = function (str) {
    return {
        n: 8,
        o: null,
        b: true,
        s: 'text',
        a: ['a', 'b', 'c'],
        f: function () {
            alert(str)
        }
    }
};
// test
s1("this function call works!").f();
// serialized object; for newbies: object is now a string and can be sent ;)
var code = s1.toString();

// RECEIVER KNOWS A WRAPPED OBJECT IS COMING IN
// you have to assign your wrapped object to somevar
eval('var s2  = ' + code);
// and then you can test somevar again
s2("this also works!").f();

请注意eval的使用。如果你拥有所有被转移的代码:随意使用它(尽管它也有缺点)。如果您不知道来源的来源:这是禁忌。

答案 5 :(得分:0)

另见JavaScript data formatting/pretty printer。我认为例程以有效的JS格式导出,因此可以通过eval来恢复它。

[编辑]其实不是!可以快速转储,但不能用于实际序列化。 我改进了它,结果如下:

function SerializeObject(obj, indentValue)
{
  var hexDigits = "0123456789ABCDEF";
  function ToHex(d)
  {
    return hexDigits[d >> 8] + hexDigits[d & 0x0F];
  }
  function Escape(string)
  {
    return string.replace(/[\x00-\x1F'\\]/g,
        function (x)
        {
          if (x == "'" || x == "\\") return "\\" + x;
          return "\\x" + ToHex(String.charCodeAt(x, 0));
        })
  }

  var indent;
  if (indentValue == null)
  {
    indentValue = "";
    indent = ""; // or " "
  }
  else
  {
    indent = "\n";
  }
  return GetObject(obj, indent).replace(/,$/, "");

  function GetObject(obj, indent)
  {
    if (typeof obj == 'string')
    {
      return "'" + Escape(obj) + "',";
    }
    if (obj instanceof Array)
    {
      result = indent + "[";
      for (var i = 0; i < obj.length; i++)
      {
        result += indent + indentValue +
            GetObject(obj[i], indent + indentValue);
      }
      result += indent + "],";
      return result;
    }
    var result = "";
    if (typeof obj == 'object')
    {
      result += indent + "{";
      for (var property in obj)
      {
        result += indent + indentValue + "'" +
            Escape(property) + "' : " +
            GetObject(obj[property], indent + indentValue);
      }
      result += indent + "},";
    }
    else
    {
      result += obj + ",";
    }
    return result.replace(/,(\n?\s*)([\]}])/g, "$1$2");
  }
}

indentValue可以为null,“”,“”,“\ t”或其他。如果为null,则没有缩进,输出相当紧凑的结果(可以使用更少的空格......)。

我可以使用数组来堆叠结果然后加入它们,但除非你有巨型对象,否则字符串连接应该足够好了...
也不处理循环引用...

答案 6 :(得分:0)

您不必使用toSource();将要序列化的代码包装在返回JSON结构的函数中,并使用function#toString()代替:

var serialized = function () {
    return {
        n: 8,
        o: null,
        b: true,
        s: 'text',
        a: ['a', 'b', 'c'],
        f: function () {
            alert('!')
        }
    }
};
serialized.toString();

查看 live demo on jsFiddle

答案 7 :(得分:0)

目前还没有人提及,所以我要指出Mozilla Object.toSourcehttps://github.com/oliver-moran/toSource.js

可以使用填充物
相关问题