JavaScript中的语法

发布 : 2018-06-04 分类 : 前端,每天学一点 浏览 :

1. 语句和表达式

开发人员常常将“语句”(statement)和“表达式”(expression)混为一谈,但这里需要将二者区别开来,因为它们在JavaScript中存在一些重要的差别。

在英语中,“句子”是完整表达某个意思的的一组词,由一个或多个“短语”(phrase)组成,它们之间由标点符合或连接词(andor等)连接起来。短语可以由更小的短语组成。有些短语是不完整的,不能独立表达意思;有些短语则相对完整,并且能够独立表达某个意思。

JavaScript的语法也是如此。语句相当于句子,表达式相当于短语,运算符则相当于标点符号和连接词。

JavaScript中表达式可以返回一个结果。例如:

1
2
3
var a = 3 * 6
var b = a
b

这里,3*6是一个表达式(结果为18)。第二行的a也是一个表达式,第三行的b也是。这三行代码都是包含表达式的语句。var a = 3 * 6var b = a 称为“声明语句”,因为它们声明了变量。a = 3 * 6b = a(不带var)叫做“赋值表达式”。

2. 语句的结果值

很多人不知道,语句都有一个结果值(undefined也算)。以赋值表达式b=a为例,其结果值是赋给b的值(18),但规范定义var的结果值是undefined。如果在控制台中输入var a=42会得到结果值undefined,而非42。

再来看看其他语句的结果。比如代码块{...}的结果值是其最后一个语句/表达式的结果。换句话说,代码块的结果值就如同一个隐式的返回,即返回最后一语句的结果值。但是语法不允许我们获得语句的结果值并将其赋值给另一个变量(至少目前不行)。

ES7规范有一项do表达式提案,类似下面这样:

1
2
3
4
5
6
7
var a,b
a = do {
if(true){
b = 4 + 38
}
}
a //42

上例中,do{...}表达式执行一个代码块,并且返回其中最后一个语句的结果值,然后赋值给变量a

3. 表达式的额副作用

大部分表达式是没有副作用的,最常见的有副作用(也可能没有)的表达式是函数调用。

其他一些表达式也有副作用,比如:

1
2
var a = 42
var b = a++

a++首先返回变量a的当前值42(再将该值赋值给b),然后将a的值加1。

很多开发人员误以为变量ba的值都是43,这是因为没有完全理解++运算符的副作用何时产生。

递增运算符++和递减运算符--都是一元运算符,它们既可以用在操作数的前面,也可以用在操作数的后面,++在前面时,如++a,它的副作用(将a递增)产生在表达式返回结果值之前,而a++的副作用则产生在之后。

** ++a++会产生ReferenceError错误,因为运算符需要将产生的副作用赋值给一个变量。它首先执行a++(根据运算符优先级,从右向左),返回42,然后执行++42,因为++无法直接在42这样的值上产生副作用,所以报错。

可以使用语句系列逗号运算符将多个独立的表达式语句串联成一个语句:

1
2
3
4
var a = 42, b
b = (a++, a)
a //43
b //43

4. 代码块

还有一个坑常被提到:

1
2
[] + {}     // "[object Object]"
{} + [] // 0

表面上看+运算符根据第一个操作数的不同会产生不同的结果,实则不然。

第一行代码中,{}出现在+运算符表达式中,因此它被当作一个值(空对象)来处理。[]会被强制类型转换为””,而{}会被强制类型转换为"[object Object]"

但在第二行代码中,{}被当作一个独立的空代码块,代码块结尾不需要分号,所以这里不存在语法上的问题。最后+变成一元操作符,将[]显式强制类型转换为0。

本文作者 : 冰比冰水冰
原文链接 : http://iceiceice.top/2018/06/04/grammar-in-javascript/
版权声明 : 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
留下足迹