概念:把一些重复的代码进行封装,在使用的时候直接调用 函数只需要定义一次,可以调用多次。
函数定义与调用
(1)函数定义
function 函数名(){ 函数体; }
函数在定义的时候,函数名后面的小括号中可以直接写变量名(变量名前不用写var),不能直接写值
(2)函数调用
函数名();
返回值、形参和实参
function getSumNumber(num1,num2){ var sum=num1+num2; return sum; } var result=getSumNumber(10,20); console.log(result);
(1)形参:函数在定义的时候,函数名后面的小括号中的变量,叫形参
(2)实参:函数在调用的时候,函数名后面的小括号中的无论是值还是变量,叫实参
(3)返回值:函数在定义的时候,函数中有 return 值; 叫返回值
(4)如果函数有return,那么该函数就有返回值;但是如果return后面没有任何的内容,该函数可以说没有明确的返回值;如果函数没有return,那么该函数没有返回值
代码:
function getSum(num1,num2) { var sum=num1+num2; console.log("和为:"+sum); } var result=getSum(10,20); //函数没有返回值,用变量来接收了 console.log(result);
控制台结果:
前者是因为getSum方法中有输出,后者因为没有返回值,所以输出undefined
函数4种形式
(1)无参数,无返回值的函数(函数中没有return,括号里没有参数)
function getSum() { var sum=num1+num2; console.log(sum); }
(2)有参数,无返回值的函数(函数中没有return,括号里有参数)
function getSum(num1,num2) { var sum=num1+num2; console.log(sum); }
(3)无参数,有返回值的函数(函数中有return,括号里没有参数)
function getSum() { var sum=num1+num2; console.log(sum); return sum; }
(4)有参数,有返回值的函数(函数中有return,括号里有参数)
function getSum(num1,num2) { var sum=num1+num2; console.log(sum); return sum; }
函数细节及注意——全重点
(1)如果直接输出函数的名字,那么显示的是函数的代码
function aa() { alert("aaa"); return function(){alert("bbb");}; } alert(aa);
结果为控制台输出:
2)在函数调用,执行函数中代码的时候,如果遇到了return,那么直接返回,并结束函数的调用,return下面的代码不会执行
(3)当一个变量声明了,没有赋值,该变量的结果是undefined;当一个函数没有明确的返回值(没有return或return后面没有任何内容),接收后的结果就是undefined.
(4)遇到系统的函数,可以按住ctrl加鼠标左键,可以查看该函数
(5)JavaScript中,实参和形参个数可以不相等,在其它语言中实参个数必须和形参个数一致
(6)
function f1(x,y,z) { var sum= x+y+z; console.log(sum); } f1(10,20);//结果为NaN,因为第3个参数z没有数据类型 f1(10,20,30);//结果为60 f1(10,20,30,40);//结果为60
(7)函数之间可以互相调用
function f1() { console.log("欢迎关注"); } function f2() { console.log("公众号"); } function f3() { f1(); console.log("前端迷"); f2(); } f3();//函数调用
控制台:
(8)js中没有函数重载的概念,函数名一旦重名了,会调用最后一个,前面的函数会被覆盖掉。(尤其不要和系统的函数名重名)
二、函数的两种定义方式
1.方式一:函数的声明
function showTime() { console.log("函数声明"); }
2.方式二:函数的表达式
//函数表达式来定义一个函数 var sayHi=function () { console.log("你好"); }; sayHi();
3.函数:命名函数和匿名函数
(1)定义:
命名函数:
函数有名字
代码
function showTime() { console.log("aaaa"); } showTime()
匿名函数:
函数没名字
代码:
var ff=function () { console.log("bbbb"); }; ff();
(2)定义的同时直接调用该函数
(function () {console.log("ccccc");})()
等价于
var ff=function () { console.log("ccccc"); }; ff();
结果都是控制台输出 ccccc
(3)函数如果是匿名函数,就不会出现重名的问题
三、JS中的块级作用域
1.理论
作用域:
变量的使用范围
块级作用域
在其它语言中,任何一对花括号(大括号{})中的语句都属于一个块,在这之中定义的所有变量在代码块外都是不可见的
JavaScript中没有块级作用域,即if,while,do-while,for这些大括号中定义的变量外部都可以访问
全局变量
定义在script或者不属于某个函数的变量
全局作用域:全局变量的使用范围
普通的全局变量和隐式全局变量
var num=10;//普通全局变量 number=100;//隐式全局变量
局部变量
定义在函数内部的变量
函数外部不能访问
局部作用域:局部变量的使用范围
一旦这个函数调用后,执行完毕了,里面的局部变量就会被释放(这块空间中的数据被删除了,空间可以为其他的程序使用)
其它
函数内部可以访问到该函数所属的外部作用域的变量(作用域链)
不使用var声明的变量是全局变量,不推荐使用。
变量退出作用域之后会销毁,全局变量关闭网页或浏览器才会销毁
2.案例
(1)if和while和for循环中定义的变量,外部可以访问
for(var i=0;i<10;i++){ var num=100; } console.log(i);//10 console.log(num);//100
(2)函数中定义的变量外部不可以访问
function f1() { var num=10; } f1(); console.log(num);
控制台输出:报错
四、函数案例
1.经典匿名函数面试题——alert(aa);、alert(aa());、alert(aa()());
function aa() { alert("aaa"); return function(){alert("bbb");}; } alert(aa); alert(aa()); alert(aa()());
(1)alert(aa);的结果为:
页面弹出
function aa() { alert(“aaa”); return function(){alert(“bbb”);}; }
(2)alert(aa());的结果为:
先弹出aaa,——执行的是aa()里的alert(“aaa”);
再弹出function(){alert(“bbb”);}——执行的是alert(aa()),弹出aa()的返回值
(3)alert(aa()());
结果为:
先弹出aaa,——执行的是aa()里的alert(“aaa”);
再弹出bbb, ——执行的是(function(){alert(“bbb”);}) (),这是定义的同时直接调用该函数
最后弹出undefined——执行的是alert();,因为function(){alert(“bbb”);}没有返回值,所以弹出undefined
2.根据年月日,显示这天是这一年的第几天
//1.判断年份是不是闰年 function isLeapYear(year) { return year%4==0&&year%100!=0||year%400==0; } //2.计算天数 function getDays(year,month,day) { //直接定义一个变量用来保存日期 var days=day; //判断这个月份是不是一月份 if(month==1){ return days; } //计算总的天数--先获取每个月有多少天5月12日 var months=[31,28,31,30,31,30,31,31,30,31,30,31]; for(var i=0;i<month-1;i++){ //因为i从0开始,所以后面为month-1,小于是因为 //3月时已经过去的是2个月,第3个月刚开始 days+=months[i]; } //判断月份要大于2月份并且是闰年 if(month>2&&isLeapYear(year)){ days++; } return days; } console.log(getDays(2016,2,15));
3.一个函数计算n个数字的和,无论传入多个数字
arguments对象——可以看成是一个数组使用,可以在函数的内部使用,可以在函数中直接通过arguments.length获取该函数在调用的时候传入了几个参数
function getSum() { //console.log(arguments.length);//看看传入几个数字 var sum=0; for(var i=0;i<arguments.length;i++){ sum+=arguments[i];//arguments[i]表示输入的第i+1个数字 } return sum; } var result= getSum(10,20,30,40);//函数调用 console.log(result);//100
4.求1-num每个数字的阶乘和function
getJieCheng(number) {
var ji=1; for(var i=1;i<=number;i++){ ji*=i; } return ji; } //求1-某个数字的阶乘和--函数做 function getSum(num) { var sum=0; //先求num之前包括num每个数字的阶乘是多少, 然后把这些阶乘相加 for(var i=1;i<=num;i++){ sum+=getJieCheng(i);//调用求阶乘方法,并求和 } return sum; } //1!+2!+3!+4!+5!=153 console.log(getSum(5));//153
5.冒泡排序
//定义函数 function mySort(arr) { //控制循环轮数 for(var i=0;i<arr.length-1;i++){ //控制每轮循环几次 for(var j=0;j<arr.length-1-i;j++){ if(arr[j]>arr[j+1]){ //从小到大。如果从大到小,arr[j]<arr[j+1] var temp=arr[j]; arr[j]=arr[j+1]; arr[j+1]=temp; } } } return arr;//返回数组 } //调用函数 var newArr=mySort([2,1,4,7,12,32,23]); console.log(newArr);
6.反转数组
function reverseArray(arr) { //反转---该循环的作用是交换的次数 for(var i=0;i<arr.length/2;i++){ var temp=arr[i]; arr[i]=arr[arr.length-1-i]; arr[arr.length-1-i]=temp; } return arr; } var newArr=reverseArray([10,20,30,40,50]); console.log(newArr);
7.斐波那契数列
function getFib(num) { var sum=0; var num1=1; var num2=1; for(var i=3;i<=num;i++){ sum=num1+num2; num1=num2; num2=sum; } return sum; } console.log(getFib(12));
8.圆的面积—π是已知的
function getS(r) { return Math.PI*r*r; } console.log(getS(5));
9.判断一个数字是不是质数function
isZhiShu(num) {
var flag=true;//假设这个数字num是一个质数 //循环 for(var i=2;i<num;i++){ if(num%i==0){ flag=false;//不是质数 break; } } return flag;//是质数 } var result=isZhiShu(8); if(result){ console.log("是质数"); }else{ console.log("不是质数"); }