JavaScript函数
目录
函数定义
函数是一个可以重复使用的程序模块,这个模块可以完成一个指定的功能。
函数的定义语法
function 函数名(参数){
函数体语句
}
在定义函数时,我们需要注意以下几点:
function:是一个关键字,必须小写
函数名:是用户标识符
参数:可以理解为参与运算的数据 ,是可选的。在接下来的代码中 我括号中的参数都不代表是绝对的,具体函数需不需要带参数还是根据我们的实际情况而定。
函数名后的()不可省略
函数体语句:用于实现功能的代码
以下为定义一个函数的代码:函数名为getSum 函数实现了100以内的所有数相加并返回sum
// 定义函数
function getSum(){
let sum = 0;
for(i = 0; i <= 100; i++){
sum += i;
}
return sum;
}
函数的调用
函数的调用分为两种情况:
1、带返回值的函数调用:也就是指函数体中有return语句的函数 let/var 变量 = 函数名()
下面代码是我们调用刚才定义的函数并输出
// 调用函数
let k = getSum();
console.log(k);
输出的结果如下:100以内所有数相加之和为5050
2、不带返回值的函数调用:函数名()
关于函数的返回值:
- 函数是否要返回值由具体的需求决定
- 函数返回值通过return语句来完成
- 如果函数是完成运算 则需要返回值 如果函数是单纯实现某种功能,则大部分情况下不需要返回值
函数的参数
函数的参数是指函数在运行时需要外部的数据才能实现具体的功能。一个函数可以有1个或者多个参数,参数之间用逗号隔开。
函数的参数有两种
1、形参
形式参数,是在函数定义时出现在函数首部的参数,并没有实际的值,可以理解为是一个占位符。
2、实参
实际参数,是在函数调用时传递给形参的。实参表示的就是一个实际值。
下面这个代码例子,可以让我们理解形参和实参 定义函数用来计算数字10的阶乘 s为形参 10为实参 我们将实参传入函数getNum的形参中计算并返回结果然后输出
function getNum(s){ //s是形参
let k = 1;
for(let i = 1; i <= s; i++){
k *= i;
}
return k;
}
let a = getNum(10);//10是实参,在函数调用时实参会传递给形参
console.log(a);
在这里我们需要注意的是,函数的调用时,参数的传递方式是实参——>形参 反之是不允许的 所以形参发生改变并不影响实参。下面这个代码可以让我们更清晰的了解实参形参的传递过程:
function swap(a,b){
console.log(`形参:${a},${b}`);
let temp = a;
a = b;
b = temp;
console.log(`形参:${a},${b}`);
}
let i = 10, j = 20;
console.log(`实参:${i},${j}`);
swap(i,j);
console.log(`实参:${i},${j}`);
以上代码输出结果为下图:
由上图我们可以看出,虽然我们在函数中改变了形参,但我们实参输出的值并未发生改变,所以由此可知,函数的参数传递是单一方向的。这点尤其需要注意。
函数参数的数量
实际上在js中是允许函数的形参与实参不同,有以下两种情况:
1、实参多余形参的情况下,调用函数后,函数可以正常运行,多余的实参则会被忽略 由下面代码我们可以更清晰的理解:
function getSum(a,b){ //a、b是形参
return a+b;
}
let t = getSum(11,22,33,55); //实参是4个
console.log(t);
2、实参少于形参的情况下,调用函数后,多出的形参是一个已声明但是未赋值的变量,输出界面则会显示undefined
function getSum(a,b,c){ //a、b、c是形参
console.log(a,b,c)
}
getSum(11,22); //实参是2个
arguments对象的使用
arguments是js的内置对象,也就是说我们无需创建,直接使用即可。
arguments的作用:调用函数时,函数的实参都保存在arguments对象中,接下来我们通过代码理解arguments的使用方法
// 定义函数getMax()
function getMax(){
// 假设最大值是第一个实参
let max = arguments[0];
// 循环遍历arguments中的实参做比较得到最大值
for(let i = 0; i < arguments.length; i++){
if(max < arguments[i]){
max = arguments[i];
}
}
return max;
}
let s = getMax(15,380,100,999);
console.log(s);
以上代码我们可以看出,我们将4个实参全部存入了arguments对象中并使用getMax()函数得到了一个最大值返回输出。
需要注意的是,每个函数内部都有一个arguments对象,本质是一个数组,保存的就是调用函数是传递的实参。
函数表达式
函数表达式是将定义的函数赋给一个变量,并且通过变量完成函数的调用和参数传递。
语法
var/let/const 变量名 = function(参数){
函数体语句
}
函数表达式的调用:变量名(参数)
//定义一个函数表达式
let max = function(a,b){
if(a > b){
return a;
}else{
return b;
}
}
//调用函数表达式并输出
console.log(`最大值:${max(10,20)}`);
由以上代码我们可以更清晰的看出 函数的调用和参数传递都是由我们定义的变量max完成的。
函数的递归调用
递归调用:指在函数体语句中调用函数本身。
递归算法:
我们首先需要明确用递归方式解决问题的前提条件:
1、问题是可以进行分解的,分解得到的新问题的解法与原问题的解法是相同的
2、问题的分解过程必须有明确的结束条件
递归过程:
1、自上而下分解问题:得到最简单的问题的解
2、自上而下回溯得到原问题的解
下面我们通过代码来了解函数的递归调用的使用
//定义函数sum
function sum(x){
// 明确条件
if(x == 100){
return 100;
}else{
// 递归调用,过程中分解问题
return x + sum(x + 1);
}
}
console.log(sum(1));
由以上代码我们可以看到定义了一个函数sum(),用来计算1+2+3...+100的值,在函数体语句中我们使用了函数的递归调用,通过递归调用的过程分解了问题,得到了我们需要的结果,所以,以后当我们看到类似情况的代码,我们就可以明白,这是使用了函数的递归调用。