Реализация метода toSource () Mozilla в Internet Explorer

Кто-нибудь реализовал метод Mozilla Object.toSource () для Internet Explorer и других браузеров, отличных от Gecko? Я ищу легкий способ сериализации простых объектов в строки.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
14
0
14 055
8

Ответы 8

Если соответствие точному формату сериализации Firefox не является вашей целью, вы можете использовать одну из библиотек сериализации / десериализации JavaScript JSON, перечисленных в http://json.org. Использование стандартной схемы, такой как JSON, может быть лучше, чем имитация проприетарного формата Gecko.

Скорее, если JSON достаточно для нужд OP, т.е. нет необходимости декомпилировать функции, разрешать циклические ссылки и т. д.

Nickolay 05.10.2008 19:08

Вы можете сделать что-то вроде этого:

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() + "}";
}

Я не эксперт по JavaScript, но Object.prototype запрещен! См .: erik.eae.net/archives/2005/06/06/22.13.54 Может быть, лучше реализовать это как бесплатную функцию.

jk. 05.10.2008 11:33

Не рекомендуется изменять прототип объекта. Также строковому типу потребуется нечто большее, чем просто экранирование \ ". Для этого потребуется экранирование \ t \ n \ r и т. д.

AnthonyWJones 05.10.2008 12:11

Замечательная идея - изменить прототип объекта, при условии, что вы знаете, как кодировать на JavaScript и не используете библиотеку (например, jQuery), которая явно выбрана неработоспособной, когда вы это делаете (в интересах повышения скорости).

Phrogz 14.02.2011 22:29

См. Также Форматирование данных JavaScript / красивый принтер. Я думаю, что подпрограмма экспортирует в допустимом формате 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, "");
  }
}

indentValue может иметь значение null, "", "", "\ t" или что угодно. Если null, без отступа, вывести довольно компактный результат (можно было бы использовать меньше пробелов ...).

Я мог бы использовать массив, чтобы сложить результаты, а затем объединить их, но если у вас нет гигантских объектов, конкатенация строк должна быть достаточно хорошей ...
Также не обрабатывает циклические ссылки ...

Если вам нужно сериализовать объекты с круговыми ссылками, вы можете использовать расширение cycle.js для объекта JSON от Дугласа Крокфорда, доступное на https://github.com/douglascrockford/JSON-js. Это работает очень похоже на toSource (), хотя не выполняет сериализацию функций (но, вероятно, может быть адаптировано для использования метода toString функции).

Учтите следующее: (при использовании 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 'infinite", откуда следует рекурсивное отступление от stackoverflow JSON.

В примерах подчеркиваются тонкости выражения, явно исключенного из представления 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 () является фактором денотационной семантики программы, влияющей, но не ограничиваясь:
вычисления в оба конца, свойства наименьшей фиксированной точки и обратные функции.

  • Есть ли повторение преобразования кода в статическое состояние?
  • Имеет ли obj.toSource () == eval (eval (eval (obj.toSource ()). toSource ()). toSource ()). toSource ()?
  • Есть ли смысл рассматривать есть ли obj == eval (obj.toSource ())?
  • Приводит ли отмена преобразования к просто похожий объект, но ИДЕНТИЧНЫЙ?
    Это загруженный вопрос с глубоким подтекстом при клонировании рабочего объекта.

и многие, многие другие ...

Обратите внимание, что приведенные выше вопросы приобретают дополнительное значение, когда obj содержит объект исполняемого кода, например (new Function ...) ()!

Вам не обязательно использовать 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();

См. живая демонстрация на jsFiddle.

Чтобы пойти немного дальше: когда вы отправляете что-то - для работы - получатель должен получить это и уметь работать с этим. Итак, следующий фрагмент кода сделает свое дело - адаптированный из предыдущего ответа Элиран Малка.

// 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. Если весь передаваемый код принадлежит вам: не стесняйтесь использовать его (хотя он также может иметь недостатки). Если вы не знаете, откуда исходит источник: это запрещено.

Никто еще не упомянул об этом, поэтому я укажу, что полифил для Mozilla Object.toSource доступен по адресу https://github.com/oliver-moran/toSource.js

Другие вопросы по теме