美文网首页
模拟JSON方法的代码理解

模拟JSON方法的代码理解

作者: Gaarahan | 来源:发表于2019-02-14 22:40 被阅读0次

    在MDN上看到了在不支持JSON的环境中对JSON的模拟代码,理解一下


    0. 代码如下:

    if (!window.JSON) {
      window.JSON = {
        parse: function(sJSON) { return eval('(' + sJSON + ')'); },
        stringify: (function () {
          var toString = Object.prototype.toString;
          var isArray = Array.isArray || function (a) { return toString.call(a) === '[object Array]'; };
          var escMap = {'"': '\\"', '\\': '\\\\', '\b': '\\b', '\f': '\\f', '\n': '\\n', '\r': '\\r', '\t': '\\t'};
          var escFunc = function (m) { return escMap[m] || '\\u' + (m.charCodeAt(0) + 0x10000).toString(16).substr(1); };
          var escRE = /[\\"\u0000-\u001F\u2028\u2029]/g;
          return function stringify(value) {
            if (value == null) {
              return 'null';
            } else if (typeof value === 'number') {
              return isFinite(value) ? value.toString() : 'null';
            } else if (typeof value === 'boolean') {
              return value.toString();
            } else if (typeof value === 'object') {
              if (typeof value.toJSON === 'function') {
                return stringify(value.toJSON());
              } else if (isArray(value)) {
                var res = '[';
                for (var i = 0; i < value.length; i++)
                  res += (i ? ', ' : '') + stringify(value[i]);
                return res + ']';
              } else if (toString.call(value) === '[object Object]') {
                var tmp = [];
                for (var k in value) {
                  if (value.hasOwnProperty(k))
                    tmp.push(stringify(k) + ': ' + stringify(value[k]));
                }
                return '{' + tmp.join(', ') + '}';
              }
            }
            return '"' + value.toString().replace(escRE, escFunc) + '"';
          };
        })()
      };
    }
    

    1. 简单理解:

    • 代码做了一个简单的判断,如果浏览器中不存在全局的JSON对象,则创建该对象,对象中有两个方法:parse()stringify()
    • JSON对象没有其他特殊的属性,只有两个方法用来在JSONJSON字符串之间转化

    2. parse()

    • parse()的代码很简单,调用eval()方法,该方法将传入的字符串当作js代码来执行

    3. stringify()

    • 写在该函数属性中的是一个立即执行表达式,该函数执行完成后,返回了一个function,这便是我们所需要的stringify()函数,这样写的好处是在函数执行完成后,我们只留下了自己需要的stringify()函数的调用入口,而在表达式中所创建的其他函数或者变量(isArray,escMap等),则以闭包的方式保留,由stringify函数内部调用,不会污染全局环境

    • 该立即执行表达式定义了将会调用的几个属性与方法,接下来判断数据的类型,对不同类型的数据定义了不同的处理方法

    • 属性与方法:
      a. toString指向Object原型上的toString()方法
      b. isArray用于判断对象是否为数组对象,其指向es6定义的Array.isArray()函数,若该方法不存在,则提供该方法的替代方法: 对该函数调用上面的toString方法,判断结果是否为[object Array]
      c. escMap,escFunc,escRE三者用来完成对unicode字符的转化,将escRE匹配到的字符,传给escFunc函数,在该函数中,依据escMap中定义的转化转义字符的规则将转义字符转化,如传入的值m不是转义字符,则将其转化为其unicode

    • 对不同数据的处理
      a. null 返回 'null'
      b. 数字:判断是否为无穷,是则返回'null',否则调用其自身的toString方法
      c. 布尔值:调用其自身的toString方法
      d. 对于对象又分为数组和(JSON)对象,判断方式同isArray中的替代方法
      数组:遍历数组元素,元素之间用,分割,并全部放入'[a,b,c]'这样的结构中
      对象:遍历对象的键值对,以"key":"value"的方式放入'{"a":"1","b":"2"}'结构中
      注意数组或者对象都是可以嵌套的,因此代码中递归调用了函数本身,处理嵌套的对象
      e. 对于其他结构,如字符串或者其他对象等,先调用其toString函数,转化为字符串,并捕获其中的unicode字符,进行替换

    相关文章

      网友评论

          本文标题:模拟JSON方法的代码理解

          本文链接:https://www.haomeiwen.com/subject/udyyeqtx.html