js语法中运算符的二义性之逗号“,”的二义性
看到《js语言精髓与编程实践》中讲解的js语法中运算符的二义性之逗号的二义性,做些笔记
我们先来看看这两个例子:
alert(eval('a=(1,2,3);'));//示例1 alert(eval('a=1,2,3;'));//示例2
结果是两者都会弹出3,这种用法产生的混乱,是因为逗号“,”既可以是语法分隔符,又可以是运算符所导致的。在上面的示例1,示例2中,逗号都被作为”连续运算符“在使用。示例1中的括号强制运算符,因此它的效果是运算如下表达式:
(1,2,3)
并将结果赋值给变量a。由于该表达式是三个(直接量的)单值表达式连续运算,其结果值是最后一个表达式,亦即是数值3.而示例2因为没有括号来强制优先级,因此按默认优先级会先完成赋值运算,效果时“变量a赋值为1”,示例2在完成赋值运算“a=1”之后,还仍将继续指向连续运算,而最后一个表达式就是直接量3。
下面来看示例3:
a=(1,2,(3,4,5),6);//示例3
同样的,我们也可以知道示例3的结果是使变量a赋值为:
[1,2,5,6]
这是因为表达式“(3,4,5)”将会被先运算并返回结果值5,作为数组声明时的一个元素。示例3中要强调的是,逗号在这里分别有“数组声明时的语法分隔符”和“连续运算符”两种作用。但是如果像示例4:
var a=1,2,3;//示例4
这样,逗号被解释成了语句var声明时用来分隔多个变量的语法分隔符,而不是连续运算符。而语句var要求用“,”号来分隔的是多个标识符,而数值2和数值3显然都不是合法的表只发,因此示例4的代码会在语法解释期就提示出错。
存在同样混乱问题的,还有下面这个示例5的例子:
//示例5.显示最后表达式的值"value:240" var i=100; alert((i+=20,i*=2,'value:'+i));
弹出“value:240”,因为在这个示例的alert()函数调用中,还存在一对括号,用来表示强制运算。因为alert()是函数,所以如果这样写:
alert(i+=20,i*=2,'value:'+i);//示例6
alert()函数会理解为三个参数传入。而函数参数表的传值顺序是从左至右的,那么示例6这行代码会被理解为:
alert(120,240,'value:240');
但alert()函数自身只会处理一个参数,因此最终显示的结果会是值“120”,而不是我们期望的240,但需要补充的是,这行代码执行完毕之后,变量i的值其实已经变成240了,为了让js理解这里的逗号“,”是连续运算符,而不是函数参数表的语法分隔符,我们在这里加入了一对强制(表达式)运算的括号,即是示例5,这样,由于外层的括号是函数调用符,因此将内部的
(i+=20,i*=2,'value:'+i)
理解为一个参数,并且是一个需要求值得表达式。因此这里的括号就顺理成章地理解成了“强制运算符”,下面的代码:
i+=20 i*=2 'value:'+i也就被作为这个强制运算符的一个运算元:由“,”连接起来的一个表达式。直到饶了这样大的一个圈子,逗号才被合理地解释为“连续运算符”。