把命令转换为表达式,循环和分支中的一些字句可以弃用,如 break、continue,以及标签语句等。变量声明语句不需要了,只需要值声明和函数内的 return 子句,其他命令都可以省略。
示例1
使用条件运算符或逻辑运算符,可以把分支结构转换为表达式。var a = ((a == 1) && console.log(1) || (a == 2) && console.log(2) || (a == 3) && console.log(3) || (a == 4) && console.log(4) || console.log(undefined) );上面代码主要利用逻辑运算符
&&
和||
来执行连续运算。对于逻辑与运算来说,如果运算符左侧的操作数为 true,才会执行右侧的操作数,否则忽略右侧的操作数;而对于逻辑或运算来说,如果运算符左侧的操作数为 false,才会执行右侧的操作数,否侧忽略右侧的操作数。逻辑与和逻辑或的组合使用可以模拟条件运算符的运算功能。这也说明 JavaScript 逻辑运算符并非是为了布尔计算来设计的,它实际上是分支结构的一种表达式化。
示例2
使用递归运算可以把循环结构转换为表达式。for(var i = 1;i < 100;i++){ console.log(i); //可执行命令 }
使用递归函数进行设计
var i = 1; (function() { console.log(i); (++i < 100) && arguments.callee(); }) ()
使用嵌套函数进一步封装。
(function () { var i = 1; return function (){ console.log(i); (++i < 100) && arguments.callee(); } })() ()
函数递归运算需要为每次函数调用保留私有空间,因此会消耗大量的系统资源。不过使用尾递归可以避免此类问题。
函数也可以作为表达式的操作数,具有值得含义。不管函数内部结构多么复杂,最终返回的只是一个值,因此可以在函数内封装复杂的逻辑。
例如,在函数中包含循环语句来执行高效运算,这样就间接的实现了把语句作为表达式的一部分投入连续运算中。在特殊环境下只能使用表达式运算,如浏览器地址栏内仅能够运行表达式代码等。
示例3
下面示例是一个连续运算的表达式,该表达式是一个分支结构,并在分支结构中包含函数体,用以判断两种表达式的大小并输出提示信息。整个代码以表达式的形式运算,与命令式语言风格迥然不同。((function f(x,y) { return (x+y) * (x+y); }) (25,36) > (function f(x,y) { return x * x + y * y; }) (25,36)) ? console.log("(x+y) ^ 2") : console.log("x ^ 2 + y ^ 2") //返回提示信息“x+y ^ 2”
示例4
下面示例使用函数封装复杂的循环结构,然后直接参与到表达式运算。console.log((function(x,y)) { var c = 0,a = [] for(var i = 0;i < x;i++){ for(var j = 0;j < y;j++) { a[c] = i.toString() + j.toString(); document.write(++c + ""); } document.write("<br />"); } return a; } )(10,10));上面代码把两个嵌套的循环结构封装在函数体内,从而实现连续求值的目的。因此,使用连续运算的表达式可以设计足够复杂的逻辑。
类似下面这种复杂的表达式也存在一定的风险,不容易阅读,也不容易调试。
console.log((function (x,y) {var c = 0,a = [];for(var i = 0;i < x;i++) {for(var j = 0;j < y;j++) {a[c] = i.toString() + j.toString();document.write (++c + "");}document.write ("<br />");}return a;}) (10,10));
应该养成良好的编码习惯,设计良好的结构可以降低代码难度。对于长表达式,应该对其进行格式化。从语义上分析,函数的调用过程实际上就是表达式运算中求值的过程。从这一点来看,在函数式编程中,函数是一种高效的连续运算的工具。例如,对于循环结构来说,使用递归运算会存在系统损耗,但是如果把循环语句封装在函数结构中,然后把函数作为值参与表达式的运算,实际上也是高效实现循环结构的表达式化。