将 JSON.stringify 改造成 JS.stringify - 毛呆的文章 - 知乎
    https://zhuanlan.zhihu.com/p/356879809

    1. const SIGN = Date.now()
    2. const LEFT_MARK = `__${SIGN}`
    3. const RIGHT_MARK = `${SIGN}__`
    4. const REGEXP = new RegExp(`"${LEFT_MARK}(.*?)${RIGHT_MARK}"`, 'g')
    5. function mark(text) {
    6. return `${LEFT_MARK}${text}${RIGHT_MARK}`
    7. }
    8. function unmark(text) {
    9. return text.replace(REGEXP, '$1')
    10. }
    11. function jsReplacer(key, value) {
    12. switch (typeof value) {
    13. case 'undefined':
    14. return mark('undefined')
    15. case 'function':
    16. return mark('<Function>')
    17. case 'number':
    18. if (Number.isNaN(value)) return mark('NaN')
    19. if (value === Infinity) return mark('Infinity')
    20. if (value === -Infinity) return mark('-Infinity')
    21. return value
    22. case 'symbol':
    23. return mark(value.toString())
    24. case 'bigint':
    25. return mark(`${value}n`)
    26. default:
    27. return value
    28. }
    29. }
    30. function createCircularReplacer() {
    31. const stack = []
    32. const keys = []
    33. function circulerText(key, value) {
    34. const valueIndex = stack.indexOf(value)
    35. const path = keys.slice(0, valueIndex + 1)
    36. return mark(`<Circular ${path.join('.')}>`)
    37. }
    38. return function (key, value) {
    39. if (stack.length === 0) {
    40. stack.push(value)
    41. keys.push('~')
    42. return value
    43. }
    44. const thisIndex = stack.indexOf(this)
    45. if (~thisIndex) {
    46. stack.splice(thisIndex + 1)
    47. keys.splice(thisIndex + 1)
    48. } else {
    49. stack.push(this)
    50. }
    51. keys.push(key)
    52. const valueIndex = stack.indexOf(value)
    53. if (~valueIndex) return circulerText(key, value)
    54. return value
    55. }
    56. }
    57. function serializer(...replacers) {
    58. const _replacers = replacers.filter((replacer) => !!replacer)
    59. return function (key, value) {
    60. return _replacers.reduce((value, replacer) => {
    61. return replacer.call(this, key, value)
    62. }, value)
    63. }
    64. }
    65. function jsStringify(value, replacer, space) {
    66. const replacers = serializer(replacer, createCircularReplacer(), jsReplacer)
    67. const reuslt = JSON.stringify(value, replacers, space)
    68. return unmark(reuslt)
    69. }