胖头鱼猜猜我有多爱你这个故事结局谁赢了的第一种结局是什么

【麦兜是只猪】 正在直播

Mac版酷狗音乐已更新

欢迎关注”前端胖头鱼“公众号,也许你为素未谋面,但很可能相见恨晚噢。

开发要对线上环境有一颗敬畏之心,任何一个点都有可能导致线上故障,也有可能让你的年终奖泡汤(⊙︿⊙)。比如使用了JSON.stringify,这个无比熟悉但又无比陌生的API。
  1. 了解一个差点让我年终奖打水漂的悲伤的故事o(╥﹏╥)o
  2. 了解如何判断一个对象是否存在循环引用 (重点)
最近组内有个小伙伴离职了,他所负责的一块业务由我去维护,结果刚接手,代码还没捂热乎,差点背上p0的锅。请让我花一点时间和你说清楚来龙去脉。
这一天胖头鱼正徜徉在代码的海洋不可自拔,突然被拉进了一个线上问题排查群,群里不可谓不热闹。

产品同学在诉苦:线上用户不能提交表单了,带来了好多客诉,估计会是p0故障,希望尽快解决。

测试同学在纳闷:这个场景测试和预发环境明明验过的,怎么线上就不行了。

后端同学在讲原因:接口缺少了value字段,导致出错了。

就是木有人说问题怎么解决!!!

就是木有人说问题怎么解决!!!

就是木有人说问题怎么解决!!!

这样的场景不知道你是不是也似曾相识呢?o(╥﹏╥)o,不管咋说第一要务还是先把线上问题解决掉,减少持续影响,赶紧把交接的代码翻出来,开始了排查过程。

如下图:有这样一个动态表单搜集页面,用户选择或者填写了信息之后(各字段非必填情况下也可以直接提交),接着前端把数据发送给后端,结束,看起来没有多复杂的逻辑。
非必填情况下,signInfo字段中经过JSON.stringify后的字符串对象缺少value key,导致后端parse之后无法正确读取value值,进而报接口系统异常,用户无法进行下一步动作。
// 异常入参数据,数组字符串中没有value key
// 默认情况下数据是这样的
// 具体原因是`undefined`、`任意的函数`以及`symbol值`,出现在`非数组对象`的属性值中时在序列化过程中会被忽略
问题的原因找到了,解决方式 (这里只讲前端的解决方案,当然也可以由后端解决) 也很简单,将value值为undefined的项转化为空字符串再提交即可。

方案一:新开一个对象处理

方案二:利用JSON.stringify第二个参数,直接处理

方案一的缺陷是需要新开一个对象进行一顿操作才能解决,不够优雅
原本这是一个已经上线有一段时间的页面,为何会突然出现这个问题,之前却没有呢?仔细询问下,原来是中途产品同学提了一个小的优化点,离职的小伙伴感觉点比较小直接就改了代码上线了,未曾想出现了线上问题。

后面针对这件事从产品到测试、到后端、到前端单独做了一个完整的复盘,细节就不再展开说了。

因为从发现问题到解决问题速度较快、影响用户数较少,还未达到问责程度,俺的年终奖可算是保住了o(╥﹏╥)o。

经过这件事情,我觉得有必要重新审视一下JSON.stringify这个方法,彻底搞清楚转换规则,并尝试手写实现一个JSON.stringify

如果你曾遇到和我一样的问题,欢迎一起来重新学习一次,一定会有不一样的收获噢!

  • 将要序列化成 一个 JSON 字符串的值。

    1. 如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理;
    2. 如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中;
    3. 如果该参数为 null 或者未提供,则对象所有的属性都会被序列化。
    1. 指定缩进用的空白字符串,用于美化输出(pretty-print);
    2. 如果参数是个数字,它代表有多少的空格;上限为10。
    3. 该值若小于1,则意味着没有空格;
    4. 如果该参数为字符串(当字符串长度超过10个字母,取其前10个字母),该字符串将被作为空格;
    5. 如果该参数没有提供(或者为 null),将没有空格。
一个表示给定值的JSON字符串。
  1. JSON.stringify可以转换对象或者值(平常用的更多的是转换对象)
  2. 可以指定replacer为函数选择性的地替换
  3. 也可以指定replacer为数组,可转换指定的属性

这里仅仅是上关于JSON.stringify其中最基础的说明,咱们先打个码试试这几个特性

以前仅仅是使用了这个方法,却没有详细了解他的转换规则,居然有9个之多。
  1. undefined任意的函数以及symbol值,出现在非数组对象的属性值中时在序列化过程中会被忽略
// 1. 对象中存在这三种值会被忽略
// 2. 数组中存在着三种值会被转化为null
布尔值数字字符串的包装对象在序列化过程中会自动转换成对应的原始值。
所有以symbol为属性键的属性都会被完全忽略掉,即便 replacer 参数中强制指定包含了它们。
转换值如果有 toJSON() 方法,该方法定义什么值将被序列化。
对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。
当尝试去转换  类型的值会抛出错误
终于重新学完JSON.stringify的众多特性啦!咱们根据这些特性来手写一个简单版本的吧(无replacer函数和space
// 确认一个对象是否存在循环引用 // 使用Set数据类型来存储已经检测过的对象 // 不是对象类型的话,可以直接跳过 // 当要检查的对象已经存在于stackSet中时,表示存在循环引用 // 对obj下的属性进行挨个检测 // 平级检测完成之后,将当前对象删除,防止误判 例如:对象的属性指向同一引用,如果不删除的话,会被认为是循环引用 // 对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。 // 当尝试去转换 BigInt 类型的值会抛出错误 // 转换值如果有 toJSON() 方法,该方法定义什么值将被序列化 // 布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值。 // 所有以symbol为属性键的属性都会被完全忽略掉,即便 replacer 参数中强制指定包含了它们。 // `undefined`、`任意的函数`以及`symbol值`,出现在`非数组对象`的属性值中时在序列化过程中会被忽略
// 1. 测试一下基本输出
// 3. 测试可遍历对象

通过上面测试可以看出,jsonstringify基本和JSON.stringify表现一致,(也有可能测试用例不够全面,欢迎提出一起学习)

因为一个BUG,重学了JSON.stringify,了解到原来它还有这么多平时没有注意到特性,前端娱乐圈水太深了,愿大家都被温柔以待,少些bug,多些关怀。晚安

我要回帖

更多关于 猜猜我有多爱你这个故事结局谁赢了 的文章

 

随机推荐