【前端三分钟】写一个JSON.Parse解析器

本文涉及的产品
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
简介: 【前端三分钟】写一个JSON.Parse解析器


//使用递归降序法
let JsonParse = function() {
    let at, //当前字符索引
      ch, //当前字符
      escapee = {
        '"': '"',
        '\\': '\\',
        '/': '/',
        b: 'b',
        f: '\f',
        n: '\n',
        r: '\r',
        t: '\t'
      },
      text,
      error = function (m) {
      //错误处理
        throw {
          name: 'SyntaxError',
          message: m,
          at: at,
          text: text
        };
      },
      next = function (c) {
        //检验c是否匹配当前字符
        if(c && c !== ch) {
          error("Expected '"+c+"' instead of'"+ ch+"'");
        }
        //获取下一个字符,当没有下一个字符时,返回空字符串
        ch = text.charAt(at);
        at +=1;
        return ch;
      },
      number = function() {
        //解析一个数字值
        let number,
          string = '';
        if(ch === '-') {
          string = '-';
          next('-');
        }
        while (ch >= '0' && ch <= '9') {
          string += ch;
          next();
        }
        if (ch === '.' ) {
          string += '.';
        }
        while (next() && ch >= '0' && ch <= '9') {
          string += ch;
        }
        if(ch === 'e' || ch === 'E') {
          string += ch;
          next();
          if (ch === '-' || ch === '+') {
            string += ch;
            next();
          }
          while (ch >= '0' && ch <= '9') {
            string += ch;
            next();
          }
        }
        number =+ string;
        if (isNaN(number)) {
          error("Bad number");
        }else {
          return number;
        }
      },
      string = function () {
        //解析一个字符串
        var hex,
          i,
          string = '',
          uffff;
        //当解析字符串值时,必须找到"和\字符
        if (ch==='"') {
          while (next()) {
            if (ch === '"') {
              next();
              return string;
            }else if (ch === '\\') {
              next();
              if (ch === 'u') {
                uffff = 0;
                for (i = 0; i < 4;i +=1) {
                  hex = parseInt(next(), 16);
                  if (!isFinite(hex)) {
                    break;
                  }
                  uffff = uffff * 16 +hex;
                }
                string += String.fromCharCode(uffff);
              }else if (typeof escapee[ch] === 'string') {
                string += escapee[ch];
              }else {
                break;
              }
            }else {
                string += ch;
            }
          }
        }
        error("Bad string");
      },
      white = function() {
        //跳过空白
        while (ch && ch <= ' ') {
          next();
        }
      },
      word = function() {
        //true,false或null
        switch (ch) {
          case 't':
            next('t');
            next('r');
            next('u');
            next('e');
            return true;
          case 'f':
            next('f');
            next('a');
            next('l');
            next('s');
            next('e');
            return false;
          case 'n':
            next('n');
            next('u');
            next('l');
            next('l');
            return null;
        }
        error("Unexpected'"+ch+"'");
      },
      array = function () {
        //解析一个数组值
        let array = [];
        if (ch === '[') {
          next('[');
          white();
        }
        if (ch === ']') {
          next(']');
          return array;//空数组
        }
        while (ch) {
          array.push(value());
          white();
          if (ch === ']') {
            next(']');
            return array;
          }
          next(',');
          white();
        }
        error("Bad array");
      },
      object = function () {
        //解析一个对象值
        let key,
          object = [];
        if (ch === '{') {
          next('{');
          white();
          if (ch === '}') {
            next('}');
            return object; //空对象
          }
          while (ch) {
            key = string();
            white();
            next(':');
            object[key] = value();
            white();
            if (ch === '}') {
              next('}');
              return object;
            }
            next(',');
            white();
          }
        }
        error("Bad object");
      },
      value = function () {
        //解析一个JSON值,它可以是对象、数组、字符串、数字或词
        white();
        switch (ch) {
          case '{':
            return object();
          case '[':
            return array();
          case '"':
            return string();
          case '-':
            return number();
          default:
            return ch >= '0' && ch<='9' ? number() : word();
        }
      };
      //返回JsonParse函数
      return function (source,reviver) {
        let result;
        text= source;
        at = 0;
        ch = ' ';
        result = value();
        white();
        if (ch) {
          error("Syntax error");
        }
        //如果存在reviver函数,则递归对这个新结构调用walk函数
        //开始时先创建一个临时启动对象,并以一个空字符串作为键名保存结果
        //如果没有reviver函数,就简单返回结果。
        return typeof reviver === 'function' ? 
          function walk(holder, key) {
            var k,v,val = holder[key];
            if(val && typeof val === 'object') {
              for(k in val) {
                if(Object.hasOwnProperty.call(val,k)) {
                  v = walk(val,k);
                  if(v !== undefined) {
                    val[k] = v;
                  }else {
                    delete val[k];
                  }
                }
              }
            }
            return reviver.call(holder,key,val);
          }({'': result},'') : result;
      }
  }();


相关文章
|
2天前
|
机器学习/深度学习 编解码 前端开发
探索无界:前端开发中的响应式设计深度解析####
【10月更文挑战第29天】 在当今数字化时代,用户体验的优化已成为网站与应用成功的关键。本文旨在深入探讨响应式设计的核心理念、技术实现及最佳实践,揭示其如何颠覆传统布局限制,实现跨设备无缝对接,从而提升用户满意度和访问量。通过剖析响应式设计的精髓,我们将一同见证其在现代Web开发中的重要地位与未来趋势。 ####
22 7
|
4天前
|
编解码 前端开发 UED
探索无界:前端开发中的响应式设计深度解析与实践####
【10月更文挑战第29天】 本文深入探讨了响应式设计的核心理念,即通过灵活的布局、媒体查询及弹性图片等技术手段,使网站能够在不同设备上提供一致且优质的用户体验。不同于传统摘要概述,本文将以一次具体项目实践为引,逐步剖析响应式设计的关键技术点,分享实战经验与避坑指南,旨在为前端开发者提供一套实用的响应式设计方法论。 ####
26 4
|
14天前
|
缓存 前端开发 JavaScript
"面试通关秘籍:深度解析浏览器面试必考问题,从重绘回流到事件委托,让你一举拿下前端 Offer!"
【10月更文挑战第23天】在前端开发面试中,浏览器相关知识是必考内容。本文总结了四个常见问题:浏览器渲染机制、重绘与回流、性能优化及事件委托。通过具体示例和对比分析,帮助求职者更好地理解和准备面试。掌握这些知识点,有助于提升面试表现和实际工作能力。
48 1
|
14天前
|
前端开发 JavaScript 开发者
揭秘前端高手的秘密武器:深度解析递归组件与动态组件的奥妙,让你代码效率翻倍!
【10月更文挑战第23天】在Web开发中,组件化已成为主流。本文深入探讨了递归组件与动态组件的概念、应用及实现方式。递归组件通过在组件内部调用自身,适用于处理层级结构数据,如菜单和树形控件。动态组件则根据数据变化动态切换组件显示,适用于不同业务逻辑下的组件展示。通过示例,展示了这两种组件的实现方法及其在实际开发中的应用价值。
22 1
|
18天前
|
缓存 前端开发 JavaScript
前端的全栈之路Meteor篇(二):容器化开发环境下的meteor工程架构解析
本文详细介绍了使用Docker创建Meteor项目的准备工作与步骤,解析了容器化Meteor项目的目录结构,包括工程准备、环境配置、容器启动及项目架构分析。提供了最佳实践建议,适合初学者参考学习。项目代码已托管至GitCode,方便读者实践与交流。
|
17天前
|
人工智能 资源调度 数据可视化
【AI应用落地实战】智能文档处理本地部署——可视化文档解析前端TextIn ParseX实践
2024长沙·中国1024程序员节以“智能应用新生态”为主题,吸引了众多技术大咖。合合信息展示了“智能文档处理百宝箱”的三大工具:可视化文档解析前端TextIn ParseX、向量化acge-embedding模型和文档解析测评工具markdown_tester,助力智能文档处理与知识管理。
|
24天前
|
人工智能 前端开发 JavaScript
拿下奇怪的前端报错(一):报错信息是一个看不懂的数字数组Buffer(475) [Uint8Array],让AI大模型帮忙解析
本文介绍了前端开发中遇到的奇怪报错问题,特别是当错误信息不明确时的处理方法。作者分享了自己通过还原代码、试错等方式解决问题的经验,并以一个Vue3+TypeScript项目的构建失败为例,详细解析了如何从错误信息中定位问题,最终通过解读错误信息中的ASCII码找到了具体的错误文件。文章强调了基础知识的重要性,并鼓励读者遇到类似问题时不要慌张,耐心分析。
|
24天前
|
JSON 前端开发 JavaScript
前端模块打包器的深度解析
【10月更文挑战第13天】前端模块打包器的深度解析
|
24天前
|
存储 前端开发 JavaScript
前端模块化打包工具的深度解析
【10月更文挑战第13天】前端模块化打包工具的深度解析
|
24天前
|
Web App开发 存储 前端开发
前端开发必备:requestAnimationFrame、setInterval、setTimeout——功能解析与优劣对比
前端开发必备:requestAnimationFrame、setInterval、setTimeout——功能解析与优劣对比
94 0

推荐镜像

更多
下一篇
无影云桌面