JavaScript重难点实例精讲
上QQ阅读APP看书,第一时间看更新

1.4.3 逗号运算符

小小的逗号在JavaScript中有很大的用处,一方面它是基本的分隔符,例如,函数传递多个参数时,使用逗号分隔。


console.log('我喜欢去%s上学习%s', '面试厅', 'JavaScript');

另一方面它可以作为一个运算符,作用是将多个表达式连接起来,从左至右依次执行。

逗号作为运算符的表现形式为:表达式1,表达式2,表达式3,……,表达式n。

它的求解过程将按照从左至右的顺序进行,优先执行表达式1,然后执行表达式2……直到执行表达式n,最后返回表达式n的结果。

例如下面的表达式语句。


x = 8 * 2, x * 4

这是一个使用了逗号运算符的语句,首先执行左边的部分,x = 8×2,即x = 16,然后执行右边的语句,x×4 = 16×4 = 64,并将其返回。

这个语句表达的意思是x的值为16,返回的值为“64”。如果将整个语句赋值给一个变量y,则该变量y的值为64。

本小节中我们将重点讲解逗号作为运算符的使用场景。

1. 在for循环中批量执行表达式

逗号运算符在for循环中的使用场景是批量执行表达式。如果一个for循环中有多个变量需要执行表达式,可以通过逗号运算符一次性执行。


for (var i = 0, j = 10; i < 10, j < 20; i++, j++) {
   console.log(i, j); 
}

一般在for循环的末尾处,只允许执行单个表达式。在这里我们通过逗号运算符,将i++和j++两个表达式视为同一个表达式,因此可以一次执行,处理i与j两个变量的递增。

2. 用于交换变量,无须额外变量

在我们需要交换两个变量的值时,通常的做法如下所示。


var a = 'a';
var b = 'b';
var c;

c = a;
a = b;
b = c;

借助临时变量c先存储a的值,然后将b值赋给a,再将c值赋给b,这样就可以实现变量交换了。

如果我们不允许使用额外的变量存储,可不可以实现呢?

当然是可以的,这里提供了两种使用逗号运算符的方案。


var a = 'a';
var b = 'b';
// 方案1
a = [b, b = a][0];
// 方案2
a = [b][b = a, 0];

在方案1中,前一部分[b, b = a]是一个一维数组,数组第二项值是b = a,实际会将a值赋给b,然后返回“'a'”,因此数组最终的值为['b', 'a'],然后取索引0的值为'b',赋给变量a,最终实现a = 'b', b = 'a'。

在方案2中,前一部分[b]是一个一维数组,后一部分[b = a, 0],实际会先执行b = a,将a值赋给b,然后返回“0”,因此后一部分实际是修改了b的值并返回索引“0”,最终是a = [b][0],即a = b,实现了a与b的交换。

3. 用于简化代码

因为逗号运算符可以使多个表达式先后执行,并且返回最后一个表达式的值,因此对于某些特定的函数,我们可以使用逗号运算符进行简写。


if (x) {
   foo();
   return bar();
} else {
   return 1;
}
// 使用逗号运算符简写后
x ? (foo(), bar()) : 1;

4. 用小括号保证逗号运算符的优先级

在所有的运算符中,逗号运算符的优先级是最低的,因此对于某些涉及优先级的问题,我们需要使用到小括号,将含有逗号运算符的表达式括起来。


var a = 20;
var b = ++a, 10;
console.log(b);  // Uncaught SyntaxError: Unexpected number

对于上面的语句,首先定义一个变量a,然后使用逗号运算符对变量a执行自增操作,同时返回“10”,并将其赋值给变量b。

我们可能会认为最后输出b的值为10,但是运行后却抛出了异常,这是为什么呢?

在上面的代码中,同时出现了赋值运算符与逗号运算符,因为逗号运算符的优先级比较低,实际会先执行赋值运算符,即先执行var b = ++a语句,再去执行后面的10,它不是一个合法的语句,所以会抛出异常。

那么我们该怎么解决这个问题呢?

那就是使用小括号,保证逗号运算符的优先级,将赋值语句后面的内容括起来,执行完含有逗号运算符的表达式后,再执行赋值语句。


var a = 20;
var b = (++a, 10);
console.log(b);  // 10