JS中Eval解析JSON字符串的一个小问题


Posted in Javascript onFebruary 21, 2016

之前写过一篇 关于 JSON 的介绍文章,里面谈到了 JSON 的解析。我们都知道,高级浏览器可以用 JSON.parse() API 将一个 JSON 字符串解析成 JSON 数据,稍微欠妥点的做法,我们可以用eval() 函数。

JSON (JavaScript Object Notation)一种简单的数据格式,比xml更轻巧。 JSON 是 JavaScript 原生格式,这意味着在 JavaScript 中处理 JSON 数据不需要任何特殊的 API 或工具包。

JSON的规则很简单: 对象是一个无序的“‘名称/值'对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值' 对”之间使用“,”(逗号)分隔

var str = '{"name": "hanzichi", "age": 10}';
var obj = eval('(' + str + ')');
console.log(obj); // Object {name: "hanzichi", age: 10}

是否注意到,向 eval() 传参时,str 变量外裹了一层小括号?为什么要这样做?

我们先来看看 eval 函数的定义以及使用。

eval() 的参数是一个字符串。如果字符串表示了一个表达式,eval() 会对表达式求值。如果参数表示了一个或多个 JavaScript 声明, 那么 eval() 会执行声明。不要调用 eval() 来为算数表达式求值; JavaScript 会自动为算数表达式求值。

简单地说,eval 函数的参数是一个字符串,如果把字符串 "noString" 化处理,那么得到的将是正常的可以运行的 JavaScript 语句。

怎么说?举个栗子,如下代码:

var str = "alert('hello world')";
eval(str);

执行后弹出 "hello world"。我们把 str 变量 "noString" 化,粗暴点的做法就是去掉外面的引号,内部调整(转义等),然后就变成了:

alert('hello world')

very good!这是正常的可以运行的 JavaScript 语句!运行之!

再回到开始的问题,为什么 JSON 字符串要裹上小括号。如果不加,是这个样子的:

var str = '{"name": "hanzichi", "age": 10}';
var obj = eval(str); // Uncaught SyntaxError: Unexpected token :

恩,报错了。为什么会报错?试试把 str "noString" 化,执行一下:

{"name": "hanzichi", "age": 10}; // Uncaught SyntaxError: Unexpected token :

毫无疑问,一个 JSON 对象或者说是一个对象根本就不是能执行的 JavaScript 语句!等等,试试以下代码:

var str = '{name: "hanzichi"}';
var obj = eval(str);
console.log(obj); // hanzichi

这又是什么鬼?但是给 name 加上 "" 又报错?

var str = '{"name": "hanzichi"}';
var obj = eval(str); // Uncaught SyntaxError: Unexpected token :
console.log(obj);

好吧,快晕了,其实还是可以将 str "nostring" 化,看看是不是能正确执行的 JavaScript 语句。前者的结果是:

{name: "hanzichi"}

这确实是一条合法的 JavaScript 语句。{} 我们不仅能在 if、for 语句等场景使用,甚至可以在任何时候,因为 ES6 之前 JavaScript 只有块级作用域,所以对于作用域什么的并不会有什么冲突。去掉 {} 后 name: "hanzichi" 也是合法的语句,一个 label 语句,label 语句在跳出嵌套的循环中非常好用,具体可以参考 label,而作为 label 语句的标记,name 是不能带引号的,标记能放在 JavaScript 代码的任何位置,用不到也没关系。

一旦一个对象有了两个 key,比如 {name: "hanzichi", age: 10},ok,两个 label 语句?将 "hanzhichi" 以及 10 分别看做是语句,但是 语句之间只能用封号连接!(表达式之间才能用逗号)。所以改成下面这样也是没有问题的:

var str = '{name: "hanzichi"; age: 10}';
var obj = eval(str); 
console.log(obj); // 10

越扯越远,文章开头代码的错误的原因是找到了,为什么套个括号就能解决呢?简单来说,() 会把语句转换成表达式,称为语句表达式。括号里的代码都会被转换为表达式求值并且返回,对象字面量必须作为表达式而存在。

本文并不会大谈表达式,关于表达式,可以参考文末链接。值得记住的一点是,表达式永远有一个返回值。大部分表达式会包裹在() 内,小括号内不能为空,如果有多个表达式,用逗号隔开,也就是所谓的逗号表达式,会返回最后一个的值。

以上所述是小编给大家介绍了JS中Eval解析JSON字符串的一个小问题,希望对大家有所帮助!

Javascript 相关文章推荐
摘自启点的main.js
Apr 20 Javascript
使用JQuery和s3captche实现一个水果名字的验证
Aug 14 Javascript
Jquery实战_读书笔记1—选择jQuery
Jan 22 Javascript
基于jQuery的表格操作插件
Apr 22 Javascript
JS实现点击文字对应DIV层不停闪动效果的方法
Mar 02 Javascript
Jquery Easyui菜单组件Menu使用详解(15)
Dec 18 Javascript
webpack配置sass模块的加载的方法
Jul 30 Javascript
解决vue单页路由跳转后scrollTop的问题
Sep 03 Javascript
详解如何制作并发布一个vue的组件的npm包
Nov 10 Javascript
深入理解vue-class-component源码阅读
Feb 18 Javascript
微信小程序连续签到7天积分获得功能的示例代码
Aug 20 Javascript
vue实现书本翻页动画效果实例详解
Apr 08 Vue.js
浏览器检测JS代码(兼容目前各大主流浏览器)
Feb 21 #Javascript
gameboy网页闯关游戏(riddle webgame)--仿微信聊天的前端页面设计和难点
Feb 21 #Javascript
全面详细的jQuery常见开发技巧手册
Feb 21 #Javascript
完善的jquery处理机制
Feb 21 #Javascript
jquery对象和DOM对象的任意相互转换
Feb 21 #Javascript
jQuery实现div拖拽效果实例分析
Feb 20 #Javascript
jQuery实现简单隔行变色的方法
Feb 20 #Javascript
You might like
PHP生成Flash动画的实现代码
2010/03/12 PHP
Laravel修改验证提示信息为中文的示例
2019/10/23 PHP
PHP实现基本留言板功能原理与步骤详解
2020/03/26 PHP
单独使用CKFinder选择图片的方法
2010/08/21 Javascript
jQuery1.3.2 升级到jQuery1.4.4需要修改的地方
2011/01/06 Javascript
jQuery.extend 函数的详细用法
2012/06/27 Javascript
jquery 判断是否支持Placeholder属性的方法
2017/02/07 Javascript
vue中element组件样式修改无效的解决方法
2018/02/03 Javascript
解决vue-router进行build无法正常显示路由页面的问题
2018/03/06 Javascript
小白教程|一小时上手最流行的前端框架vue(推荐)
2019/04/10 Javascript
js仿360开机效果
2019/12/26 Javascript
js实现动态时钟
2020/03/12 Javascript
javascript实现多边形碰撞检测
2020/10/24 Javascript
[53:21]2014 DOTA2国际邀请赛中国区预选赛5.21 DT VS LGD-CDEC
2014/05/22 DOTA
python中sets模块的用法实例
2014/09/30 Python
python实现决策树ID3算法的示例代码
2018/05/30 Python
说说如何遍历Python列表的方法示例
2019/02/11 Python
计算机二级python学习教程(1) 教大家如何学习python
2019/05/16 Python
python 判断文件还是文件夹的简单实例
2019/06/10 Python
python脚本当作Linux中的服务启动实现方法
2019/06/28 Python
在tensorflow中实现屏蔽输出的log信息
2020/02/04 Python
jupyternotebook 撤销删除的操作方式
2020/04/17 Python
解决python对齐错误的方法
2020/07/16 Python
法拉利英国精品店:Ferraris Boutique UK
2019/07/20 全球购物
struct与class的区别
2014/02/03 面试题
说一下mysql, oracle等常见数据库的分页实现方案
2012/09/29 面试题
广州足迹信息技术有限公司Java软件工程师试题
2014/02/15 面试题
历史学专业大学生找工作的自我评价
2013/10/16 职场文书
会计专业自荐信范文
2013/12/02 职场文书
小小的船教学反思
2014/02/21 职场文书
学校校庆演讲稿
2014/05/22 职场文书
紧急通知
2015/04/17 职场文书
2015年教师见习期工作总结
2015/05/20 职场文书
Redis安装使用RedisJSON模块的方法
2022/03/23 Redis
Redis超详细讲解高可用主从复制基础与哨兵模式方案
2022/04/07 Redis
python计算列表元素与乘积详情
2022/08/05 Python