如何实现一个JS中的stringify函数

420 阅读1分钟

在javascript里面,JSON.stringify是最常用的内置方法之一,这里尝试实现一个简易版的stringify

要实现stringify,首先要注意JSON.stringify的特点,为了简便,暂不考虑第二个replacer参数和第三个缩进参数,只考虑其它序列化特点:

  1. 忽略undefined:如果直接传一个undefiend给JSON.stringify,它会返回undefined;如果一个对象某个key的值是undefined,那么会忽略这个key,如果一个数组里面有undefined,那么忽略这些undefined的位置
  2. 忽略函数:特征跟undefined在数组,对象中类似,如果直接传函数给JSON.stringify,则也会返回undefined
  3. 忽略不可枚举属性
  4. 忽略原型属性 根据以上特点,使用递归加遍历的方法来实现:
function stringify(obj) {
  if (obj === null) {
    return 'null';
  }
  if (typeof obj === 'function') {
    return undefined;
  }
  if (typeof obj === 'object') {
    if (Array.isArray(obj)) {
      const strList = [];
      Object.values(obj).forEach(value => {
        if (value !== undefined) {
          strList.push(stringify(value));
        }
      });
      const str = strList.join(',');
      return '[' + str + ']'
    } else {
      const strList = []
      Object.keys(obj).forEach(key => {
        if (obj[key] !== undefined) {
          strList.push('"' + key + '":' + stringify(obj[key]));
        }
      });
      const str = strList.join(',');
      return '{' + str + '}'
    }
  } else {
    if (obj !== undefined) {
      if (typeof obj === 'string') {
        return '"' + obj + '"';
      }
      return String(obj);
    }
    return undefined;
  }
}

在实现的过程中有几点需要注意:

  1. 必须使用全等(===)来判断undefined,==会将undefiend和null视为相等
  2. 使用===来判断null,因为typeof null值为'object',故需要单独判断
  3. 使用Array.isArray(ES6)来判断数组比使用instanceof Array更加严谨,因为Array不同document中的Array构造函数是被视作不同的,假设页面中有个iframe,产生的问题如下所示:
const frame = document.querySelector('frame');
const arr = [];
console.log(arr instanceof frame.contentWindow.Array) // false
console.log(frames[0].window.Array.isArray(arr)); // true