概述
Function与函数
函数是这样的一段、JavaScript代码,它只定义一次,但可能被执行或调用多次。
Function类型是JavaScript提供的引用类型之一, 通过Function类型创建Function对象。
在JavaScript中,函数也是以对象的形式存在的。每个函数都是一个Function对象。
函数名,本质就是一个 变量名,是指向某个Function对象的引用。
function fn(){
console.log('喵');
}
console.log(fn instanceof Function); // true
Function类型
构造函数
在JavaScript中,函数除了可以通过函数定义语句或字面量表达式两种方式定义之外,还可以通过Function类型进行定义:
var add = new Function(
"num1",
"num2"
"var num = num1 + num2; return sum;"
)
注意:通过Function类型定义函数的效率远不如通过函数定义语句或字面量表达式两种方式定义。
目前,定义函数具有三种方式,这三种方式之间存在一定差别:
定义方式 | 执行 | 效率 |
---|---|---|
函数定义语句 | 函数名被声明提前 | 不存在效率问题 |
字面量表达式 | 函数体固定,无法动态执行 | 不存在效率问题 |
Function类型定义 | 函数体是字符串,可以动态执行 | 效率低 |
Function的apply()方法
Function的apply()方法用于调用一个函数,并且接收指定的this值,以及一个数组作为参数。其语法结构如下:
func.apply(thisArg,[argsArray])
- thisArg参数:可选项,在func函数运行时使用的this值。
- argsArray参数:可选项,一个数组或者类数组对象,其中的数组元素将作为单独的参数传递给func函数。也可以使用arguments对象作为该参数。
- 返回值:调用该函数的返回结果。
var numbers = [5,6,2,3,7];
// 通过apply()方法获取数组中最大值和最小值
var max = Math.max.apply(null,numbers);
var min = Math.min.apply(null,numbers);
Function的call()方法
Function的call()方法用于调用一个函数,并且接收指定的this值作为参数,以及参数列表。其语法结构如下:
func.call(thisArg,arg1,arg2,...)
- thisArg参数:在func函数运行时使用的this值。
- arg1,arg2,…参数:指定的参数列表。
- 返回值:调用该函数的返回结果。
apply()与call()非常相似,不同之处在于提供参数的方式。
// 通过call()方法获取数组中最大值和最小值
var max = Math,max.call(null,5,6,2,3,7);
var min = Math.min.call(null,5,6,2,3,7);
Function的bind()方法
Function的bind()方法用于创建一个新的函数(称为绑定函数),井且接收指定的this值作为参数,以及参数列表。其语法结构如下:
fun.bind(thisArg[,arg1[,arg2[,...]]])
- thisArg参数:当绑定函数被调用时,该参数会作为原函数运行时的this指向。
- arg1,arg2,…参数:当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。
- 返回值:返回由指定的this值和初始化参数改造的原函数拷贝。
没有重载
在其他开发语言中,函数具有一种特性,叫做重载。所谓重载,就是定义多个同名的函数,但每一个函数接收的参数的个数不同,程序会根据调用时传递的实参个数进行判断,具体调用的是哪个函数。如下示例:
function add(a,b){
return a + b;
}
function add(a,b,c){
return a + b + c;
}
add(1,2);// 3
add(1,2,3);// 6
递归
在一个函数的函数体内,如果想调用自身函数的话,有如下两种方式:
- 通过使用自身函数名实现。
- 通过使用arguments对象的callee属性实现。
调用自身的函数被称为递归函数。在某种意义上说,递归近似于循环。两者都重复执行相同的代码,并且两者都需要一个终止条件以避免无限循环或者无限递归。
function loop(x){
if(x >= 10){return;}
loop(x+1);
}
loop(0);
上述代码是一个经典的递归函数。 虽然这个函数表面看起来并没有什么问题,如果执行下述代码可能会导致出错。
var anotherLoop = loop;
loop = null;
anotherLoop(0);// 出错
上述代码将函数loop()保存到另一个变量anotherLoop中,然后将loop设置为null值。当执行anotherLoop时,一定会执行函数loop(),而loop已经不再是一个函数,最终导致出错。
要想解决上述递归函数的问题,可以使用arguments对象的callee属性替换具体的函数名。
function loop(x){
if(x >= 10){
return;
}
arguments.callee(x+1);
}