JavaScript语法对{}的奇葩处理

JavaScript的语法有多坑,算是众人皆知了。html

今天看到vczh的这条微博:http://weibo.com/1916825084/B7qUFpOKb ,数组

 代码以下:浏览器

{} + [];    // 0
[] + {};    // "[object Object]"
{} + [] == [] + {};    // false
({} + [] == [] + {});    // true

 

这么蛋疼的语法坑估计也只有 JavaScript 这样的奇葩才有。函数

相信对于绝大部分不研究 JavaScript 编译器的童鞋,根本没法理解。(至少我也是以为难以想象)spa

后来看到有人在转发中贴出了这篇文章,才有点恍然大悟!.net

 

下面,咱们先看看这个代码:code

{
    a: 1
}

相信大部分童鞋,第一眼都会认为这是一个 对象直接量 htm

那这个代码呢?对象

{
    var a = 1;
}

浏览器会提示语法错误吗?blog

显然不会!细想一下,咱们就会明白到,这是一个 语句块

if (1) {
    var a = 1;
}

 

说到这里,敏锐的你可能已经发现:JavaScript 中以「{」开头,会存在二义性。即,它有多是一个 对象直接量,也多是一个 语句块

那 JavaScript 的编译器是怎么处理这个二义性的?

为了解决这个问题,ECMA 的方法十分简单粗暴:在语法解析的时候,若是一个语句以「{」开头,就只把它解释成语句块。

这真心是一个坑爹的处理方式!

那既然都是语句块,那为何 {a:1} 却没有语法错误?

其实在这里,a 被解析器理解为了 标签标签 是用来配合 break 和 continue 语句做定向跳转的。

所以,这样的写法就会抛出异常:

{
    a: function () {}
}

由于 function () {}  不是函数声明,也不是函数表达式。

 

到这里,你们应该对 {} 的奇葩处理有了基本的概念。咱们再看回文章开始所提到的几条语句:

{} + [];    // 0
[] + {};    // "[object Object]"
{} + [] == [] + {};    // false
({} + [] == [] + {});    // true

第一条,由于是「{」开头,被解析器解析为 语句块,代码能够理解为:

if (1) {}
+[]

因此返回值是 0 。

第二条,因为「{」并不在语句的开头,因此是一个正常的 对象直接量,空数组和空对象直接相加,返回 "[object Object]" 。

理解了第一第二条,第三条已经无需解释了。

第四条,由于是「(」开始,第一个 {} 被解析为 对象直接量 ,于是两条公式相等,返回 true。

 

 

参考资料:

http://typeof.net/s/jsmech/02.html

 

 

本文做者:Maple Jan

本文连接:http://www.cnblogs.com/maplejan/p/3768010.html

相关文章
相关标签/搜索