Вызвать заменитель *до* объекта toJSON?

Есть ли способ вызвать мой заменитель прежде чем собственный toJSON объекта преобразует его, чтобы я мог работать с исходным объектом, а не с его удобной для JSON формой, без переопределения toJSON на объекте или его прототипе, предварительная обработка объекта или написание собственной версии JSON.stringify?

Например: предположим, что я хочу сериализовать Date экземпляра иначе, чем их обычная сериализация (то есть toISOString). (Этот вопрос не относится к Date, это просто пример.) Проблема в том, что мой заменитель не видит объект Date, он видит строку (см. фрагмент ниже), потому что Date.prototype.toJSON вызывается перед моим заменителем.

var obj = {
  d: new Date()
};
snippet.log(getType(obj.d));     // "[object Date]"

var json = JSON.stringify(obj, function(key, value) {
  if (key === "d") {
    snippet.log(getType(value)); // "string" <== Want to see a Date here
  }
  return value;
});

function getType(value) {
  var to = typeof value;
  if (to === "object") {
    to = Object.prototype.toString.call(value);
  }
  return to;
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Есть ли способ вызвать реплейсера первым? Я не хочу переопределять Date.prototype.toJSON, предварительно обрабатывать объект или писать свой собственный JSON.stringify, но другого пути я не вижу.


person T.J. Crowder    schedule 03.03.2015    source источник


Ответы (2)


Если я понимаю, что вы правы, это должно помочь, я уверен, что this всегда является объектом, который JSON.stringify в настоящее время выполняет итерацию:

var json = JSON.stringify(obj, function(key, value) {
  if (key === "d") {
    snippet.log(getType(this[key]));
  }
  return value;
});
person t.niese    schedule 03.03.2015
comment
Красивый. Он даже работает в исключительных случаях, когда вы вводите в строку фрагмент документа (JSON.stringify(new Date())), а не весь документ, благодаря шагам 9–11. - person T.J. Crowder; 03.03.2015

Из MDN:

Объект, в котором был найден ключ, предоставляется как параметр this заменителя.

Итак, вы можете сделать это:

var obj = {
  d: new Date()
};
snippet.log(getType(obj.d));     // "[object Date]"

var json = JSON.stringify(obj, function(key, value) {
  if (key === "d") {
    snippet.log(getType(this[key]));
  }
  return value;
});

function getType(value) {
  var to = typeof value;
  if (to === "object") {
    to = Object.prototype.toString.call(value);
  }
  return to;
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

person JLRishe    schedule 03.03.2015
comment
Спасибо. Я знал, что должен быть лучший способ. :-) - person T.J. Crowder; 03.03.2015