eval及json的理解

假如你现在还在为自己的技术担忧,假如你现在想提升自己的工资,假如你想在职场上获得更多的话语权,假如你想顺利的度过35岁这个魔咒,假如你想体验BAT的工作环境,那么现在请我们一起开启提升技术之旅吧,详情请点击http://106.12.206.16:8080/qingruihappy/index.html

 

 一,案例一

 1 <br><br>
 2 复制代码
 3 var str = '{"name": "hanzichi", "age": 10}';
 4 var obj = eval('(' + str + ')');
 5 console.log(obj); // Object {name: "hanzichi", age: 10}
 6 是否注意到,向 eval() 传参时,str 变量外裹了一层小括号?为什么要这样做?
 7  
 8 我们先来看看 eval 函数的定义以及使用。
 9  
10 eval() 的参数是一个字符串。如果字符串表示了一个表达式,eval() 会对表达式求值。如果参数表示了一个或多个 JavaScript 声明, 那么 eval() 会执行声明。不要调用 eval() 来为算数表达式求值; JavaScript 会自动为算数表达式求值。
11  
12 简单地说,eval 函数的参数是一个字符串,如果把字符串 "noString" 化处理,那么得到的将是正常的可以运行的 JavaScript 语句。
13  
14 怎么说?举个栗子,如下代码:
15  
16 复制代码
17 var str = "alert('hello world')";
18 eval(str);
19 执行后弹出 "hello world"。我们把 str 变量 "noString" 化,粗暴点的做法就是去掉外面的引号,内部调整(转义等),然后就变成了:
20  
21 复制代码
22 alert('hello world')
23 very good!这是正常的可以运行的 JavaScript 语句!运行之!
24  
25 再回到开始的问题,为什么 JSON 字符串要裹上小括号。如果不加,是这个样子的:
26  
27 复制代码
28 var str = '{"name": "hanzichi", "age": 10}';
29 var obj = eval(str);  // Uncaught SyntaxError: Unexpected token :
30 恩,报错了。为什么会报错?试试把 str "noString" 化,执行一下:
31  
32 复制代码
33 {"name": "hanzichi", "age": 10};  // Uncaught SyntaxError: Unexpected token :
34 毫无疑问,一个 JSON 对象或者说是一个对象根本就不是能执行的 JavaScript 语句!等等,试试以下代码:
35  
36 复制代码
37 var str = '{name: "hanzichi"}';
38 var obj = eval(str);
39 console.log(obj); // hanzichi
40 这又是什么鬼?但是给 name 加上 "" 又报错?
41  
42 复制代码
43 var str = '{"name": "hanzichi"}';
44 var obj = eval(str);  // Uncaught SyntaxError: Unexpected token :
45 console.log(obj);
46 好吧,快晕了,其实还是可以将 str "nostring" 化,看看是不是能正确执行的 JavaScript 语句。前者的结果是:
47  
48 复制代码
49 {name: "hanzichi"}
50 这确实是一条合法的 JavaScript 语句。{} 我们不仅能在 iffor 语句等场景使用,甚至可以在任何时候,因为 ES6 之前 JavaScript 只有块级作用域,所以对于作用域什么的并不会有什么冲突。去掉 {} 后 name: "hanzichi" 也是合法的语句,一个 label 语句,label 语句在跳出嵌套的循环中非常好用,具体可以参考 label,而作为 label 语句的标记,name 是不能带引号的,标记能放在 JavaScript 代码的任何位置,用不到也没关系。
51  
52 一旦一个对象有了两个 key,比如 {name: "hanzichi", age: 10},ok,两个 label 语句?将 "hanzhichi" 以及 10 分别看做是语句,但是 语句之间只能用封号连接!(表达式之间才能用逗号)。所以改成下面这样也是没有问题的:
53  
54 复制代码
55 var str = '{name: "hanzichi"; age: 10}';
56 var obj = eval(str); 
57 console.log(obj); // 10
58 越扯越远,文章开头代码的错误的原因是找到了,为什么套个括号就能解决呢?简单来说,() 会把语句转换成表达式,称为语句表达式。括号里的代码都会被转换为表达式求值并且返回,对象字面量必须作为表达式而存在。
59  
60 本文并不会大谈表达式,关于表达式,可以参考文末链接。值得记住的一点是,表达式永远有一个返回值。大部分表达式会包裹在() 内,小括号内不能为空,如果有多个表达式,用逗号隔开,也就是所谓的逗号表达式,会返回最后一个的值。
61  
62 说到表达式,不得不提函数表达式,以前翻译过一篇关于立即执行函数表达式的文章,可以参考下,文末。
大家知道使用eval()函数可以将JSON格式字符串转换为对象直接量。

先看一段转换JSON字符串的代码实例:

[JavaScript]  纯文本查看 复制代码运行代码
1
2
var  obj=eval( '({"webName":"antzone","age":2,"address":"青岛市南区"})' );
console.log(obj.webName);

由上面代码的运行结果可以看出,转换获得了成功,也可以看到,在JSON格式字符串外面又嵌套了一层小括号。

下面就来介绍这层小括号的作用,需要的朋友可以做一下参考。

eval()函数会创建一个执行环境,如果没有加小括号,{"webName":"antzone","age":2,"address":"青岛市南区"}会被解释成一个复合语句(大括号是用来构建复合语句的),那么"webName":和后面的内容也无法组成一个标签语句,直接就报错了,即便不是标准的JSON字符串,如{webName:"antzone",age:2,address:"青岛市南区"},webName:和后面的内容形成一个标签语句,"antzone"是一个字符串字面量,age就是一个变量,但是跟冒号就会报错。如果外面嵌套一个小括号,小括号是分组运算符,那么{"webName":"antzone","age":2,"address":"青岛市南区"}就是一个表达式,这时会被解读为一个对象直接量,就不会有任何问题了。

 

 

 二,案例二

在JS中将JSON的字符串解析成JSON数据格式,一般有两种方式:

1.一种为使用eval()函数。

2. 使用Function对象来进行返回解析。

使用eval函数来解析,并且使用jquery的each方法来遍历

用jquery解析JSON数据的方法,作为jquery异步请求的传输对象,jquery请求后返回的结果是json对象,这里考虑的都是服务器返回JSON形式的字符串的形式,对于利用JSONObject等插件封装的JSON对象,与此亦是大同小异,这里不再做说明。 
这里首先给出JSON字符串集,字符串集如下:

代码如下:
var data=" 

root: 

{name:'1',value:'0'}, 
{name:'6101',value:'北京市'}, 
{name:'6102',value:'天津市'}, 
{name:'6103',value:'上海市'}, 
{name:'6104',value:'重庆市'}, 
{name:'6105',value:'渭南市'}, 
{name:'6106',value:'延安市'}, 
{name:'6107',value:'汉中市'}, 
{name:'6108',value:'榆林市'}, 
{name:'6109',value:'安康市'}, 
{name:'6110',value:'商洛市'} 
]
}"; 
这里以jquery异步获取的数据类型——json对象和字符串为依据,分别介绍两种方式获取到的结果处理方式。

1.对于服务器返回的JSON字符串,如果jquery异步请求没做类型说明,或者以字符串方式接受,那么需要做一次对象化处理,方式不是太麻烦,就是将该字符串放于eval()中执行一次。这种方式也适合以普通javascipt方式获取json对象,以下举例说明:

var dataObj=eval("("+data+")");//转换为json对象

Red rose为什么要 eval这里要添加 “("("+data+")");//”呢?

原因在于:eval本身的问题。 由于json是以”{}”的方式来开始以及结束的,在JS中,它会被当成一个语句块来处理,所以必须强制性的将它转换成一种表达式。

加上圆括号的目的是迫使eval函数在处理JavaScript代码的时候强制将括号内的表达式(expression)转化为对象,而不是作为语句(statement)来执行。举一个例子,例如对象字面量{},如若不加外层的括号,那么eval会将大括号识别为JavaScript代码块的开始和结束标记,那么{}将会被认为是执行了一句空语句。所以下面两个执行结果是不同的:
alert(eval("{}"); // return undefined
alert(eval("({})");// return object[Object]

对于这种写法,在JS中,可以到处看到。

三,案例三

eval函数的工作原理

eval函数会评估一个给定的含有JavaScript代码的字符串,并且试图去执行包含在字符串里的表达式或者一系列的合法的JavaScript语句。eval函数将把最后一个表达式或者语句所包含的值或引用作为返回值。

举例说明

  • eval评估JavaScript表达式
var bar = 'bar';
var foobar = eval('"foo" + bar');
alert(foobar);
  • eval评估JavaScript语句
var bar = 'bar';
// if variable bar equals 'bar', foobar is the result of
// last executing statement: bar="foo-bar";
var foobar = eval('if(bar == "bar") {bar="foo-bar";} else {bar = "bar-foo";}');
alert(foobar);
// change the value
bar = 'foo';
// now our the last executed statement is: bar = "bar-foo";
// therefore the value of variable foobar has been changed
// into 'bar-foo'
foobar = eval('if(bar == "bar") {bar="foo-bar";} else {bar = "bar-foo";}');
alert(foobar);

JSON的格式

JSON的格式是由大括号和由冒号(:)构成的名值对所组成的。注意JSON格式与对象字面量 (object literals) 的区别:JSON的名字部分严格用引号+名字来表示。

举例说明

  • 对象的字面量
var objectLiteral = {
name: "Objector.L",
age: "24",
special: "JavaScript",
sayName: function() {
return this.name;
}
};
  • JSON对象
var jsonFormat = {
"summary": "Blogs",
"blogrolls": [
{
"title": "Explore JavaScript",
"link": "http://example.com/"
},
{
"title": "Explore JavaScript",
"link": "http://example.com/"
}
]
};

eval和JSON

由于Ajax的兴起,JSON这种轻量级的数据格式作为客户端与服务器之间的传输格式逐渐地流行起来,进而出现的问题是如何将服务器端构建好的JSON数据转化为可用的JavaScript对象。利用eval函数无疑是一种简单而直接的方法。在转化的时候需要将JSON字符串的外面包装一层圆括号:

var jsonObject = eval("(" + jsonFormat + ")");

为什么要加括号?

加上圆括号的目的是迫使eval函数在评估JavaScript代码的时候强制将括号内的表达式(expression)转化为对象,而不是作为语句(statement)来执行。举一个例子,例如对象字面量{},如若不加外层的括号,那么eval会将大括号识别为JavaScript代码块的开始和结束标记,那么{}将会被认为是执行了一句空语句。所以下面两个执行结果是不同的:

alert(eval("{}"); // return undefined
alert(eval("({})");// return object[Object]

JSON格式的名字部分为什么要加引号?

因为eval函数会将{foo:”bar”}解释成合法的JavaScript语句,而非表达式。但是人们往往想要的是让eval将这段代码解释成一个对象。所以JSON格式会强制你去在名字的外侧加上引号再结合圆括号,这样eval就不会错误的将JSON解释成代码块。

举例说明

  • eval错误解析语义
alert(eval('{foo:"bar"}')); // return "bar", incorrect
  • eval正确解析JSON
alert(eval('({"foo": "bar"})')); // return JSON object, correct

结论

理解eval的工作原理和json的严格的限定格式,合理结合eval和json应用于JavaScript的数据传递和对象转换。

following this format:

eval('{' + jsonString + ')');// code removed by author at 2010-01-03
 
  

eval('(' + jsonString + ')');
 
  
 
 

 四:案例四

 对JS中的eval一知半解,不知eval是如何把字符串转换为json对象的,在用eval把字符串转换为json时常遇到“missing ] after element list”错误却不知哪儿错了的朋友

 

一、Eval介绍(这部分来自http://www.w3school.com.cn/js/jsref_eval.asp)

  定义和用法:eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。

  语法:eval(string)

  参数string:必需。要计算的字符串,其中含有要计算的 JavaScript 表达式或要执行的语句。

  返回值:通过计算 string 得到的值(如果有的话)。

  说明:该方法只接受原始字符串作为参数,如果 string 参数不是原始字符串,那么该方法将不作任何改变地返回。因此请不要为 eval() 函数传递 String 对象来作为参数。如果试图覆盖 eval 属性或把 eval() 方法赋予另一个属性,并通过该属性调用它,则 ECMAScript 实现允许抛出一个 EvalError 异常。

  异常:如果参数中没有合法的表达式和语句,则抛出 SyntaxError 异常。如果非法调用 eval(),则抛出 EvalError 异常。如果传递给 eval() 的 Javascript 代码生成了一个异常,eval() 将把该异常传递给调用者。

 五:解析

首先我们来看eval的定义

定义和用法:eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。

  语法:eval(string)

  参数string:必需。要计算的字符串,其中含有要计算的 JavaScript 表达式或要执行的语句。

  返回值:通过计算 string 得到的值(如果有的话)。

意思就是说eval的参数是一个字符串,但是这个字符串必须是符合js表单式的语句。

例如

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

这样就会弹出hello world的字样

首先"alert('hello world')"是一个字符串

而alert('hello world')是符合JavaScript 的表单式

返回值就是JavaScript 的表单式的返回值。

 

我们再来看另一个案例:

var foobar = eval('if(bar == "bar") {bar="foo-bar";} else {bar = "bar-foo";}');
alert(foobar);

道理是一样的。

 

那么我们来看一下为什么在json格式的数据外要加小括号呢。

首先我们来分析一下,一个json不是一个符合 JavaScript 表达式的语句,那么怎么把它变成一个符合javascript的表单式呢。

通过下面的这篇博客,我们可以

JavaScript小括号、中括号、大括号的多义性

函数:声明和表达式中表达式函数的解析,就是在一段代码加上小括号就可以变成表达式函数。在这里面就是把申明式函数加小括号变成了表达式函数。同样可以在字符串加上小括号变成表达式函数。

 function func(){};//函数声明方式
(function func(){})//函数表达式方式

深入探究javascript的 {} 语句块

 看出小括号就有把json格式的字符串,强制转化成符合JavaScript 表达式的语句的语句,

这也就是为什么要加小括号的作用了。

 

此外,我们还可以看到这样的解释

加上圆括号的目的是迫使eval函数在评估JavaScript代码的时候强制将括号内的表达式(expression)转化为对象,而不是作为语句(statement)来执行。举一个例子,例如对象字面量{},如若不加外层的括号,那么eval会将大括号识别为JavaScript代码块的开始和结束标记,那么{}将会被认为是执行了一句空语句。所以下面两个执行结果是不同的:

alert(eval("{}"); // return undefined
alert(eval("({})");// return object[Object]

 在这种解释的情况下。我们必须要理解小括号()的作用。

 

此外,额外的小知识点,

{name: "hanzichi"}

这种情况是符合JavaScript 表达式的语句的。

'{name: "hanzichi"; age: 10}';也符合。它就是一个lable的格式语句。

至于为什么符合,请见

浅谈Javascript中的Label语句

 

其中name 就相当于一个label ,而后面的值就相当于一个for 循环的语句,是 符合JavaScript 表达式的语句的,假如是两个以上的组合的话就用符合符合JavaScript 表达式的语句的;表示

 

假如你现在还在为自己的技术担忧,假如你现在想提升自己的工资,假如你想在职场上获得更多的话语权,假如你想顺利的度过35岁这个魔咒,假如你想体验BAT的工作环境,那么现在请我们一起开启提升技术之旅吧,详情请点击http://106.12.206.16:8080/qingruihappy/index.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值