作者:张耀国(igorzhang)
函数
函数就是把完成特定的功能的代码段封装起来,给该功能起一个名字(函数名),封装好该功能后,哪里需要调用该功能就在哪里去调用即可,函数可以在任何时间任何地点进行调用。
使用函数的好处:
1、是程序变得简洁明了
2、有利于后期的代码维护
3、可以提高程序的开发效率
4、提高了代码的复用性
总结:之前不使用函数的情况下,JS代码必须按照顺序去执行,并且执行代码的那部分和执行时间都是不可控的。但是声明函数后,浏览器不会直接去执行它,只有我们在想使用它的时候才会去执行,很灵活。
函数的分类:
1、系统自带的函数:alert() parseInt()...
2、自定义的函数:根据自己需求定义的函数。
自定义函数的使用步骤:
1、声明一个函数(定义)。
2、调用这个函数(在任何时候,任何地方都可以调用)
声明函数的语法如下:
用function关键字去声明一个函数
function 函数名字(参数1,参数2,……) {//参数根据需求可有可无
//执行函数的内容
return 返回值; //根据需求返回值可有可无.
}
调用函数的语法如下:
函数名字(参数值1,参数值2.……); //参数根据该函数声明时是否有参数而定
总结一下:
1、function关键字,定义函数的关键字,必须有!
2、函数名(符合标识符的定义标准)。必须有(过后我们会学习匿名函数,情况会特殊一下)!
3、参数列表,在声明的时候--就是一些标识符,根据情况可由可无。如果有的话,有一个参数或者多个参数。在采用的时候--是具体要传入的值,根据情况可有可无。
4、函数体{},函数内就是将来要执行的代码,返回值根据情况可有可无。
printKiss();//在这里能调用的原因是:JS帮我们做了一个声明提前。
//声明一个无参数,无返回值的函数。
//函数的功能是打印“要亲亲,要抱抱,要举高高”
function printKiss () {
console.log("要亲亲,要抱抱,要举高高。"); //函数不调用是不会走这段代码的。
}
printKiss(); //调用函数,想调用多少次都行。
printKiss();
printKiss();
//声明一个无参数,有返回值的函数。
//函数的功能,获得“我们是H5-10期的好孩子。”这句话
function getClassName () {
return "我们是H5工程师。"; //return关键字表示立即停止函数的运行,并且返回相应的内容。暂时这个学习阶段,我们只会返回一些基本类型,例如数值型,字符串型,布尔型等,高级阶段return还可以返回对象类型和另外一个函数。
}
var className = getClassName();//因为函数有返回值,所以调用的时候用一个变量去接受该函数的返回值。
console.log(className); // 此时控制台输出“我们是H5工程师”
//return可以立即停止函数的运行,类似于循环结构中的break关键字。return可以给返回值,也可以不给。但不管给不给返回值,只要写return了,就可以立刻停止函数的运行。
function testFn() {
var a =10;
var b = 20;
if(b > a) {
//return b; //会返回b的值,并且中断函数的运行下面代码都不会执行。
return "那肯定不能执行啊";//这里可以有返回值,也可以不写返回值,根据自己需求而定。
}
console.log("你觉得我这段代码能执行吗?");
}
var maxNum = testFn();//函数的调用,并且结接受返回值给maxNum,如果函数没有返回值的话,则接受后则是underfined
console.log(maxNum); // 控制台输出“那肯定不能执行啊” ,说明程序满足if条件后被return打断了。
//函数体内,也可以调用另外一个函数
function fn1 () {
// var name = fn2(); //函数内调用另外一个函数,可以再函数内直接调用
// console.log(name);
// return name + "耀国国";
return fn2() + "耀国国"; // 也可以调用后作为返回值输出
}
function fn2 () {
return "给fn1函数提供的数据!";
}
var str = fn1(); //想执行以上代码,必须要先调用fn1函数。
console.log(str); // 此时控制台就输出 “给fn1函数提供的数据!耀国国”
匿名函数
匿名函数:“没有函数名:。将来会用到真正的”没有函数名“的函数,例如:函数作为回调函数的时候,作为返回值的时候。
匿名函数和正常函数做的事情是一样的,都需要声明和调用。
//这样直接暴露在程序外面是错误的,除非将来学习到高阶函数的时候,作为返回值或者参数是可以的。
function () {
console.log("我是一个匿名函数");
}
fn1()
注意:匿名函数这种方式,不支持声明提前。所以不要再还没有声明函数的时候调用,会报错--fn1 is not a function
//声明一个匿名函数
var fn1 = function () {
console.log("我是一个匿名函数");
}
fn1 () ;//和正常函数一样,想使用必须调用一下才行
函数的参数
函数的参数分为形参和实参。
形参:函数声明时用的。
实参:函数调用时用的。
形参其语法如下:
function fn (str) { //其中str就是形参,符合标识符声明的规则,过后调用fn后传进来的实参是什么值,这个str就代表那个值。
console.log(str); //在函数体中,形参就和普通变量一样,该如何使用就如何使用。
}
实参语法如下:
fn(123); //123 就是实参(说白了就是具体的值),给函数声明时的形参用的。
注意:在大部分编程语言中。实参的个数与形参的个数和类型是相同的。但是对于JS而言,不会检查实参和形参的个数和类型。
调用函数,传参相当于赋值,将实参的值赋值给形参。
声明一个带参数的函数
function fn (name) { //name就是形参,一会调用的时候就会赋值给她
console.log("大家好,我叫:" + name);
}
fn("张耀国");
fn("羊羊羊");
声明一个带多个参数的函数
function fn2 (name,age,sex) { //声明多个参数,参数之间用“,”隔开。
console.log("名字是:" + name + "\n年龄是:" + age + "\n性别是:" + sex);
}
fn2('张耀国','18','男');
声明带多个形参的函数,但是实参个数不确定
function fn3 (a,b,c) { //声明的时候是3个形参
console.log(a);
console.log(b);
console.log(c);
}
fn3(); //不传任何参数 不会报错,最多是形参是underfined.
fn3(20); //传一个实参的话,就会赋值给第一个形参,后面如果有其他形参的话参数值是underfined
fn3(12,23,34,45,56,67); //穿入的实参个数大于形参个数,只去依次匹配形参,多余的没用
声明时不给参数
function fn4 () { //声明的时候没有给任何形参
//每个函数体内都有一个arguments对象(参数数组)里面存贮了传进来的所有参数)
//获取第一个参数的语法是arguments[0],从0开始,获取第二个参数arguments[1]...依次类推
console.log(arguments[0]);
console.log(arguments[1]);
//通过arguments.length 获取参数的个数
console.log(arguments.length);
}
函数的重载
所谓函数的重载,是指大部分面向对象语言中的概念,指的是函数名字相同,但参数不同(参数个数不同,参数类型不同)。注意:在JS中没有函数重载的概念,如果出现函数名字相同的情况,那么后面的会覆盖掉前面的函数。
function sayHello(name){
console.log("我的名字叫做:" + name );
}
//函数名字和上面的函数一样,那么不会实现重载,而会覆盖掉上面的函数。
function sayHello(name,age){
console.log("我的名字叫做:" + name + ",年龄:" +age);
}
sayHello("zyg"); // 函数名相同,只调用第二个函数
sayHello("aaa",19);
递归函数
递归函数:所谓递归函数,就是函数本身调用自己,通过改变步进条件,来终止函数的运行。
补充:一般用循环的解决的问题,用递归也能解决。
递归写法
function fn2(num){
//最终停止递归调用的临界条件,当num等于0时,程序结束
if(num == 0){
return;
}
console.log(num);
num--;
fn2(num); //递归调用
}
fn2(5); // 实参传入5,函数运行后控制台会分五次输出5,4,3,2,1
声明一个函数,传入一个数值,实现这个数值的阶乘,所谓阶乘,例如5的阶乘就是 5 x 4 x 3 x 2 x 1 特殊:0的阶乘也是1
递归用到的公式(num的阶乘):num * (num - 1)的阶乘
function fn3(num){
if(num == 1){
return 1;
}
return num * fn3(num - 1);
// 随着递归的调用,最终调用结果相当于 5 * 4 * 3 * 2 *1
}
console.log(fn3(5));