定义函数
定义函数(自定义函数)
函数就是功能、方法。函数能够帮我们封装一段代码,这一段代码会具备某一项功能,函数在执行时,封装这一段都会执行一次,实现某种功能。
而且,函数可以多次调用。
一、函数的定义和调用
语法:
定义:把需要实现的功能预先做好
执行:在需要的时候执行这个功能,而且可以根据需要多次执行
定义:function name(){ }
执行:name();
语法解释:
function 定义函数的关键字
name 函数名称
() 参数集
{} 函数体,执行的代码都放在{}中
//定义一个函数,函数就是一组语句的集合 function haha(){ console.log(1); console.log(2); console.log(3); console.log(4); } haha(); //调用haha函数 haha(); //调用haha函数 haha(); //调用haha函数
函数的意义1:在出现大量程序相同的时候,可以封装为一个function,这样只调用一次,就能执行很多语句。
二、函数的参数
定义在函数内部的语句,都是相同的,但是实际上可以通过“参数”这个东西,来让语句有差别。
定义函数的时候,内部语句可能有一些悬而未决的量,就是变量,这些变量,要求在定义的时候都罗列在小括号中
function fun(a){ console.log("第"+ a +"次说爱你"); } fun(100); fun(1); fun(2); fun(3);
运行结果:
实参(实际参数)和形参(形式参数)
罗列在function小括号中的参数,叫做形式参数;调用时传递的值,叫做实际参数。每次调用都可以传递不同的参数
function fun(a,b){ console.log(a + b); } fun(3,5); //输出8 fun(8,20); //输出28 fun("10",24); //输出1024,做的是连字符串 fun(10); //输出NaN,因为计算的就是10+undefined = NaN fun(10,20,30,40,50); //输出30,只有前两个参数被形参接收了,后面的参数无视
函数的意义2:在调用一个函数的时候,不用关心函数内部的实现细节,甚至这个函数是你上网抄的,可以运用。
function sum(m,n){ var s = 0; for(var i = m; i <= n;i++){ s = s + i; } console.log(s); } sum(1,100); //5050 计算1+....+100 sum(10,13); //10+11+12=13 sum(10,10000); sum(13,10); //输出0,所以你就知道了函数的顺序关机,定义顺序是什么,传递顺序就是什么。 sum(1,6);
三、函数的返回值
函数可以通过参数来接收东西,更可以通过return的语句来返回值,“吐出”东西。
function sum(a,b){ return a+b; //现在这个函数的返回值是a+b的和 } console.log(sum(2,3));//sum没有输出功能,要用console.log输出,计算sum(2,3)实际上成为一个表达式,需要计算,计算后就是5 console.log(sum(3,sum(4,5)));//输出12,实际上有两次执行了sum函数,先执行最内层,计算出9,然后sum(3,9),结果就是12
函数可以接收很多值,返回一个值。
函数意义3:模块化编程,让复杂的逻辑变得简单。
函数只能有唯一的return,有if语句除外。
程序遇见return,将立即返回结果,返回调用它的地方,而不执行函数内后面剩余的语句。
function fun(){ console.log(1); console.log(2); return; //返回一个空值,undefined console.log(3); //这行语句不执行,因为函数已经return了,所以会终止执行后面的代码 } console.log(fun());
结果为:
四、应用函数简化编程-模块化
实现前提:函数有返回值,可以作为其他函数执行时传的实参。
习惯将复杂工作,进行一步步的分工,将一部分工作的结果作为下一步工作的条件。
将程序中某个单独的功能制作成单独函数,这就是造轮子的过程。
业务逻辑上:将所有的轮子进行拼装。
将程序分成有层次的模块,制作过程中一部分函数要有返回值,执行结果作为另一些模块的参数、条件。
案例:输出1~1000的所有的质数。所谓质数,就是只有1、自己两个约数,没有其他约数
逻辑思维:约数个数→判断质数
<script type="text/javascript"> //封装约数个数的函数: 能传入一个数字,实现这个数约数的个数 function yueshugeshu(a){ var count=0; for(var i=1; i<=a; i++){ if(a%i==0){ count++; } } return count; //返回这个数约数的个数 } //判断是否是质数,如果一个函数名字取is,就暗示将返回布尔值。通常是真假做法,不是规定 function isZhiShu(m){ if(yueshugeshu(m)==2){ return true; }else{ return false; } } //判断1到1000的质数 for(var i=1; i<=1000; i++){ if(isZhiShu(i)){ console.log(i); } } </script>
五、函数的递归
函数可以自己调用自己,就是递归。
function haha(){ console.log("哈哈"); haha(); //调用自己 } haha();
案例
斐波那契数列就是经典的递归算法:
输出斐波那契数列:
1、1、2、3、5、8、13、21、34、55、89、144、233...
只需要一个函数,就可以搞定全部问题
fib(n) 就能得到第n位的数字
fib(2) = 1
fib(5) = 5
fib(6) = 8
fib(10) = 55
function fib(n){ if(n==1 || n==2) { return 1; }else{ return fib(n-1)+fib(n-2) } } // -点点计算 for(var i=1; i<=55; i++){ console.log(fib(i)); }
六、函数表达式
定义函数除了使用function之外,还要一种方法,就是函数表达式。就是函数没有名字,称为“匿名函数”。
为了今后能够调用它,我们会把这个匿名函数,直接赋值给一个变量。
var haha = function(){ console.log(1) } haha();
等价于
function haha(){ console.log(1); } haha(); //以后想调用这个函数的时候,就可以直接使用haha变量调用
七、函数声明的提升(预解析)
//先调用 fun(); //可以输出,因为函数有函数声明头提升的特性 fun(); fun(); //后定义 function fun(){ console.log("我是函数,我执行了"); }
JS在执行前,会有一个预解析的过程,把所有的函数声明,都提升到最最开头,然后再执行第一行语句。
所以,function定义在哪里,都不重要,程序总能找到这个函数
fun2(); var fun2 = function(){ //这是函数表达式,而不是function定义法 console.log("我是函数,我执行了"); }
结果为
函数声明会被提升,但是函数表达式却不会被提升
八、函数是一个引用类型
之前说过,基本类型:number、string、Boolean、undefined、null
引用类型也有很多种:object、function、array、RegExp、Math、Date
var haha = function(){ } function fun(){ } console.log(typeof haha); //引用类型中的function类型 console.log(typeof fun); //引用类型中的function类型