Кто-нибудь применил метод Mozilla Object.toSource() для Internet Explorer и других браузеров, не связанных с Gecko? Я ищу легкий способ сериализации простых объектов в строки.
Внедрение метода Mozilla toSource() в Internet Explorer
Ответ 1
Учитывайте следующее: (при использовании 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 #]
и сообщение "going" бесконечное ", откуда следует рекурсивное отступление JSON stackoverflow.
В примерах подчеркиваются тонкости выражения, явно исключенные из представления JSON, которые отображаются с помощью toSource().
Нелегко составить программу для тиражирования тех же результатов для ВСЕХ случаев, как примитив 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() является фактором денотационной семантики программы, влияющей, но не ограничиваясь:
расчеты в оба конца, наименьшие свойства фиксированной точки и обратные функции.
- Повторяется ли конвертация кода quiesce в статическое состояние?
- Выполняет obj.toSource() == Eval (Eval (Eval (obj.toSource()). toSource()). toSource()). toSource()?
- Имеет смысл рассмотреть obj == eval (obj.toSource())?
- Отменяет результат преобразования, а не
просто подобный объект, но
ИДЕНТИЧНЫЙ?
Это загруженный вопрос с глубокими последствиями при клонировании операционного объекта.
и многие, многое другое...
Обратите внимание, что приведенные выше вопросы приобретают дополнительное значение, когда obj содержит исполняемый объект кода, такой как (новая функция...)()!
Ответ 2
Если соответствие точного формата сериализации Firefox не является вашей целью, вы можете использовать одну из библиотек сериализации/десериализации JavaScript JSON, перечисленных в http://json.org. Использование стандартной схемы, такой как JSON, может быть лучше, чем подражать запатентованному формату Gecko.
Ответ 3
Если вам нужно сериализовать объекты с помощью круговых ссылок, вы можете использовать расширение cycle.js для объекта JSON Дугласом Крокфордом, доступным по адресу https://github.com/douglascrockford/JSON-js. Это очень похоже на toSource(), хотя он не будет сериализовать функции (но, вероятно, может быть адаптирован к использованию метода toString).
Ответ 4
Вы можете сделать что-то вроде этого:
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() + "}";
}
Ответ 5
Чтобы сделать это немного дальше: когда вы отправляете что-то - для работы - получатель должен получить его и иметь возможность работать над ним. Таким образом, этот следующий бит кода будет делать трюк, адаптированный из предыдущего ответа 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
. Если у вас есть весь передаваемый код: не стесняйтесь использовать его (хотя он также может иметь недостатки). Если вы не знаете, откуда источник: это нет-нет.
Ответ 6
См. также форматирование данных JavaScript/красивый принтер. Я думаю, что обычный экспорт в действительный формат JS, поэтому он может быть оценен, чтобы вернуть его.
[EDIT] На самом деле, нет! Это нормально для быстрой свалки, но не для реальной сериализации. Я улучшил его, результат ниже:
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 может быть нулевым, "," "," \ t" или любым другим. Если null, no indentation, выводит довольно компактный результат (можно использовать меньше пробелов...).
Я мог бы использовать массив, чтобы складывать результаты, а затем присоединяться к ним, но если у вас нет гигантских объектов, конкатенация строк должна быть достаточно хорошей...
Также не обрабатывает циклические ссылки...
Ответ 7
Вам не нужно использовать 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 на jsFiddle.
Ответ 8
Никто еще не упомянул об этом, поэтому я укажу, что есть polyfill для Mozilla Object.toSource
в https://github.com/oliver-moran/toSource.js