为什么eval里面要加圆括号?

2014-05-18 jude 更多博文 » 博客 » GitHub »

原文链接 http://judes.me/frontend/2014/05/18/eval-why.html
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。


最近在 JavaScript DOM 高级程序设计上看到这样一段代码:

try {
    j = eval('(' + s + ')')
} catch(e){
    throw new SyntaxError("parseJSON");
}

为什么eval内部的 s 要用圆括号围起来呢?

书上的解释:因为 s 是JSON格式的数据,形式是这样的:{key1:val1,key2:val2},其中“{”操作符具有语法上的二义性:它既可以定义一个语句块,也可以表示对象字面量,用圆括号围起来是让它表示对象字面量。

如果要深入了解背后的原理,就要先知道几个概念:语句、表达式及分组操作符。

以下内容引自代码之谜(二)- 语句与表达式

"表达式"(expression)是一个单纯的运算过程,总是有返回值;

"语句"(statement)是执行某种操作,没有返回值。

表达式的特点

  • 会返回一个值
  • 可放在任何一个需要值的地方
  • 存在于表达式上下文当中
  • 表达式的一部分也是表达式
  • 表达式可以代替(本该出现的)语句,此时的表达式称为表达式语句

语句的特点

  • 不会返回值
  • 存在于语句上下文中
  • 语句不能代替(本该出现的)表达式,例如不能把语句作为函数的参数

圆括号:(),是分组操作符,分组操作符只能包含表达式

还需要知道的一点是,eval会将其参数放进 语句上下文 中解释

我们要传进eval中解释的是一个对象字面量,是一个值。所以要传进去的是一个表达式,如果不加圆括号,这个表达式就会被解释成表达式语句,圆括号可在语句上下文内产生新的一个表达式上下文来避免这一点。

参考文献