JavaScript 提供了 4 种函数调用:一般形式的函数调用、作为对象的方法调用、使用 call 和 apply 动态调用、使用 new 间接调用。
一般形式的函数调用
在默认状态下,函数是不会被执行的。使用小括号()
可以激活并执行函数。在小括号中可以包含零个或多个参数,参数之间通过逗号进行分隔。
示例1
在下面示例中,使用小括号调用函数,然后直接把返回值传入函数,进行第二次运算,这样可以节省两个临时变量。
- function f(x,y) { //定义函数
- return x * y; //返回值
- }
- console.log(f(f(5,6), f(7,8))); //返回1680。重复调用函数
示例2
如果函数返回值为一个函数,则在函数调用时可以使用多个小括号反复调用。
- function f(x,y) { //定义函数
- return function () { //返回函数类型的数据
- return x * y;
- }
- }
- console.log(f(7,8) ()); //返回56,反复调用函数
示例3
设计递归调用函数,即在函数内调用自身,这样可以反复调用,但最终返回的都是函数自身。
- function f() { //定义函数
- return f; //返回函数自身
- }
- console.log(f() () () () () () () () () () () ()); //返回函数自身
当然,上述设计方法在实际开发中没有任何应用价值,不建议使用。
作为对象的方法调用
当一个函数被设置为对象的属性值时,称之为方法。使用点语法可以调用一个方法。
示例
下面示例创建一个 obj 对象,它有一个 value 属性和一个 increment 属性。increment 方法接收一个可选参数,如果该参数不是数字,那么默认使用数字 1。
- var obj = {
- value : 0,
- increment : function (inc) {
- this.value += typeof inc === 'number' ? inc :1;
- }
- }
- obj.increment();
- console.log(obj.value); //1
- obj.increment(2);
- console.log(obj.value); //2
使用点语法可以调用对象 obj 的方法 increment,然后通过 increment 方法改写 value 属性的值。在 increment 方法中可以使用 this 访问 obj 对象,然后使用 obj.value 方式读写 value 属性值。
使用 call 和 apply 动态调用
call 和 apply 是 Function 的原型方法,它们能够将特定函数当做一个方法绑定到指定对象上,并进行调用。具体用法如下:
function.call(thisobj, args...)
function.apply(thisobj, [args])
function 表示要调用的函数;参数 thisobj 表示绑定对象,即 this 指代的对象;参数 args 表示要传递给被调用函数的参数。call 方法可以接收多个参数列表,而 apply 只能接收一个数组或者伪类数组,数组元素将作为参数列表传递给被调用的函数。
示例1
下面示例使用 call 动态调用函数 f,并传入参数值 3 和 4,返回运算值。
- function f(x,y) { //定义求和函数
- return x + y;
- }
- console.log(f.call (null, 3, 4)); //返回7
在上面示例中,f 是一个简单的求和函数,通过 call 方法把函数 f 绑定到空对象 null 身上,以实现动态调用函数 f,同时把参数 3 和 4 传递给函数 f,返回值为 7。实际上,f.call(null,3,4) 等价于 null.m(3,4)。
示例2
上面示例使用 call 调用,实际上也可以使用 apply 方法来调用函数 f。
- function f(x,y) { //定义求和函数
- return x + y;
- }
- console.log(f.apply(null, [3,4])); //返回7
如果把一个数组或伪类数组的所有元素作为参数进行传递,使用 apply 方法就非常便利。
示例3
下面使用 apply 方法设计一个求最大值得函数。
- function max() { //求最大值函数
- var m = Number.NEGATIVE_INFINITY; //声明一个负无穷大的数值
- for (var i = 0; i < arguments.length; i ++) { //遍历所有实参
- if (arguments[i] > m) //如果实参值大于变量m
- m = arguments[i]; //则把该实参值赋值给m
- }
- return m; //返回最大值
- }
- var a = [23,45,2,46,62,45,56,63]; //声明并初始化数组
- var m = max.apply(Object, a); //动态调用max,绑定为Object的方法
- console.log(m); //返回63
在上面示例中,设计定义一个函数 max(),用来计算所有参数中的最大值参数。首先通过 apply 方法动态调用 max() 函数,然后把它绑定为 Object 对象的一个方法,并把包含多个值的数组传递给它,最后返回经过 max() 计算后的最大数组元素。
如果使用 call 方法,就需要把数组所有元素全部读取出来,再逐一传递给 call 方法,显然这种做法不是很方便。
示例4
也可以动态调用 Math 的 max() 方法来计算数组的最大值元素。
- var a = [23,45,2,46,62,45,56,63]; //定义并初始化数组
- var m = Math.max.apply(Object, a); //调用系统函数max
- console.log(m); //返回63
示例5
使用 call 和 apply 方法可以把一个函数转换为指定对象的方法,并在这个对象上调用该方法。当函数动态调用之后,这个对象的临时方法也就不存在了。
- function f() {
- return "函数f";
- }
- var obj = {};
- f.call(obj); //把函数f绑定为obj对象的方法
- console.log(obj.f()); //再次调用该方法,则返回编译错误
call 和 apply 方法的主要功能如下:
- 调用函数。
- 修改函数体内的 this 指代对象。
- 为对象绑定方法。
- 跨越限制调用不同类型的方法。
本小节主要介绍了如何使用 call 和 apply 方法调用函数,由于涉及类型、对象和 this 知识,后续我们还会继续深入讲解。
new 命令间接调用
使用 new 命令可以实例化对象,这是它的主要功能,但是在创建对象的过程中会激活并运行函数。因此,使用 new 命令可以间接调用函数。
示例
下面示例简单演示了如何用 new 命令,把传入的参数值显示在控制台。
- function (x,y) { //定义函数
- console.log("x =" + x + ", y =" + y);
- }
- new f(3,4);
使用 new 命令调用函数时,返回的是对象,而不是 return 的返回值。如果不需要返回值,或者 return 的返回值是对象,则可以选用 new 间接调用函数。