
1.1.4 复合函数
我们已经介绍了JavaScript里的一些元素,它们必然也会出现在任何一种强大的程序设计语言里,包括:
●数和算术运算是基本的数据和函数。
●组合式的嵌套提供了一种把多个操作组织起来的方法。
●常量声明是一种受限的抽象手段,其功能就是为名字关联值。
现在我们来学习函数声明,这是一种威力更强大的抽象技术,通过它可以给复合操作确定一个名字,而后就可以把它作为一个单元来引用。
我们从如何表述“平方”的概念开始。我们可能说“求某个东西的平方,就是用它自身去乘它自身”。在我们的语言里,这件事应该表述为:

可以按如下方式理解这一描述:

这样我们就有了一个复合函数,它还被命名为square。这个函数表示把一个东西乘以其自身的操作。被乘的东西给定了一个局部名x,它扮演着与自然语言里的代词同样的角色。求值这一声明的结果就是创建出一个复合函数,并把它关联于名字square[6]。
最简单的函数声明的形式是:

其中的name是一个名字,函数的定义将在环境中关联于这个名字[7]。parameters(形式参数)是一些名字,它们被用在函数体里,表示要求引用在应用这个函数时提供的各个实参。这些parameters写在一对括号里,用逗号分隔,就像所声明的函数被实际调用时的写法。在最简单的形式里,这里的body就是一个返回语句,由关键字return和一个返回表达式构成[8]。在函数应用时,声明中的形式参数被与之对应的实参取代,返回表达式的执行生成函数应用的值。与常量声明和表达式语句一样,返回语句最后也需要有分号。
声明了square之后,我们就可以在函数应用表达式里使用它。我们可以给这种表达式加上分号,将其转变为一个语句:

除了运算符组合式,函数应用是我们遇到的第二种组合表达式,它们同样可用于构造更大的表达式。函数应用的一般形式是:

应用中的function-expression(函数表达式)描述希望应用的函数,要求将其应用于逗号分隔的那些argument-expression(实参表达式)。在求值一个函数应用式时,解释器将按下面的过程工作,类似于1.1.3节描述的运算符组合式的求值过程:
需要求值一个函数应用式时,按下面的方式工作:
1.求值应用式中的各个子表达式,即其中的函数表达式和各个实参表达式。
2.把得到的函数(也就是函数表达式的值)应用于那些实参表达式的值。

这里的实参表达式本身又是组合式,即为运算符组合式2+5。

很自然,实参表达式同样也可以是函数应用表达式。
我们还可以用square作为基本构件去声明其他函数。举例说,x2+y2可以描述为:

现在我们很容易声明一个函数sum_of_squares[9],给它两个数作为实参,它就能给出这两个数的平方和:

现在我们又可以用sum_of_squares作为构件,进一步去构造其他函数了:

除了复合函数之外,每个JavaScript环境都提供了一些基本函数,它们被构筑在解释器里,或者可以从函数库装入。除了为各个运算符提供相应的基本函数,本书使用的JavaScript环境还包括了另外一些基本函数,例如函数math_log,它计算实参的自然对数值[10]。基本函数的使用方式与复合函数一样,math_log(1)将得到数值0。实际上,如果只看上面给出的sum_of_squares的声明,我们根本没办法分辨其中的square究竟是直接构筑在解释器里,或是从程序库装入,还是通过声明定义的复合函数。