JS把命令式语句转换为表达式

在表达式运算中,求值是运算的核心。由于运算只产生值,因此可以把所有命令式语句都转换为表达式,并进行求值。

把命令转换为表达式,循环和分支中的一些字句可以弃用,如 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));

应该养成良好的编码习惯,设计良好的结构可以降低代码难度。对于长表达式,应该对其进行格式化。从语义上分析,函数的调用过程实际上就是表达式运算中求值的过程。从这一点来看,在函数式编程中,函数是一种高效的连续运算的工具。例如,对于循环结构来说,使用递归运算会存在系统损耗,但是如果把循环语句封装在函数结构中,然后把函数作为值参与表达式的运算,实际上也是高效实现循环结构的表达式化。