5.9 案例实战
本节将通过多个题型化案例强化读者对表达式的运算,同时训练运算符的灵活应用能力。在训练之前,建议先不看参考答案和解析。
5.9.1 表达式计算
下面列举14个表达式,请快速计算出它们的值:
1.1 && 3
2.1 && "foo" || 0
3.1 || "foo" && 0
4.(1,2,3)
5.{foo:1}[0]
6.[true, false][+true, +false]
7.++'52'.split('')[0]
8."b" + 45
9.[1,2,3,4,5][0..toString.length]
10.({} + 'b' > {} + 'a')
11.x = 1; (function(){return x; var x = 2; }())
12.'foo' == new function(){ return String('foo'); };
13.'foo'.split('') + []
14.vars: var vars = vars
答案和解析:
1.3
解析:布尔值在"&&"运算时,如果左为true时,总是返回右边,反之则直接返回左边。
2."foo"
解析:布尔值在"||"运算时,如果左为false时,总是返回右边,反之则直接返回左边。
3.1
解析:原因同上一道题。
4.3
解析:", "运算,直接输出最后一个。
5.underfined
解析:{foo:1}中无key为“0”的属性,没有该属性,则返回默认值underfined。
6.true
解析:[+true, +false]为[1,0],整体[true, false][1,0]中,[1,0]可看作", "运算,所以整体简化为[true, false][0]。
7.6
解析:'52'.split('')为["5", "2"], ++["5", "2"][0]为6。
8."b45"
解析:隐式转换为字符串相连接。
9.2
解析:[0..toString.length]相当于(0).toString.length。
10.true
解析:相当于比较字符串"[object Object]b"和"[object Object]a"。
11.undefined
解析:没有变量接收自执行函数返回值。
12.false
解析:"foo"为字符串,new function为对象。
13."f, o, o"
解析:先把字符串’foo’劈开为数组,然后与空数组相加,则直接返回字符串的值。
14.undefined
解析:第一个标识符vars为标签,第二个标识符vars为变量,把声明的变量vars赋值给自己,则返回值还是默认值undefined。
5.9.2 表达式描述
类似下面形式的表达式在编程实践中会经常使用,请说明这行代码是什么意思,为什么要这样写?
foo = foo||bar
解析:
上面表达式可以转换为if语句:
if(! foo) foo = bar;
如果变量foo存在,则保持该变量的值不变,否则把bar的值赋给foo,即设置变量foo的初始值。上面表达式俗称为短路表达式,它灵活应用了&&和||运算符。这类表达式在进行求值时,只要最终结果已经可以确定是真或假,求值过程便终止。
5.9.3 编程题
编写一个求和函数sum(),要求达到如下情况和返回值效果。
sum(1,2,3,4,5); //返回值为15 sum(5, null, -5); //返回值为0 sum('1.0', false,1, true,1, 'A',1, 'B',1, 'C',1, 'D',1, 'E',1, 'F',1, 'G',1); //返回值为10 sum(0.1,0.2); //返回值为0.3,而不是0.30000000000000004
解析:
本题包含两个知识训练点:一是如何剔除非数字参数,二是如何处理浮点数溢出问题。
排除非数字参数,可以有多种方法,最简洁的方法是使用parseFloat()函数与||运算符结合。先使用parseFloat()函数把参数转换为浮点数,如果成功则加上转换后的数值,否则加0,排除转换中的NaN值。
浮点数溢出可以通过升位浮点数为整数相加,然后再降位实现,最后使用toFixed()方法去掉溢出小数即可。
参考:
function sum() { var nResult = 0; for (var i = 0, l = arguments.length; i < l; i++) { nResult += 1000 * parseFloat(arguments[i]) || 0; } return nResult.toFixed(3) / 1000; } alert(sum(0.1, 0.2))