一、简介
函数是用来完成特定功能的代码块,可以被调用执行多次,实现复用
分类:
- 内置函数
- 自定义函数
二、内置函数
函数名 | 含义 |
---|---|
typeof() | 判断变量的类型 |
isNaN() | 判断参数是否为NaN |
parseInt() | 将数据转换为整数 |
parseFloat() | 将数据转换为小数 |
eval() | 计算字符串表达式的值,并执行其中的JavaScript代码 |
encodeURI() | 使用ISO8859-1 对字符串进行编码,每个UTF-8的汉字编码成3个16进制字节,如下: %字节1%字节2%字节3 |
decodeURI() | 使用ISO8859-1 对字符串进行解码 |
escape() | 使用Unicode 对字符串进行编码,每个UTF-8的汉字被编码成一个双字节16进制转义字符%uXXXX ,中文范围%u4e00---%u9fa5 |
unescape() | 使用Unicode 对字符串进行解码 |
//以上在前面讲过,可看前面回顾//1.eval() 计算字符串表达式的值,并执行其中的JavaScript代码var str="2+5";console.log(eval(str));//2.encodeURI()和decodeURI()var str="浅笑心柔";//使用ISO8859-1编码var B=encodeURI(str);console.log(B);//使用ISO8859-1解码var J=decodeURI(B);console.log(J);//3.escape()和unescape()var S="你好世界"//使用Unicode编码var b=escape(S);console.log(b);//使用Unicode解码var j=unescape(b);console.log(j);
三、自定义函数
1、语法:
// 1.定义函数
function 函数名(参数1,参数2...){ // 形参// 函数体
}// 2.调用函数
函数名(参数1,参数2...); // 实参
示例:
//1.定义函数function f1(){var sum=0;for(var i=1;i<=100;i++){sum+=i;}console.log("从1到100的和为:"+sum);} //2.调用函数f1();//f1();可以多次调用函数,实现对应的功能//定义带一个参数的函数function f2(num){//形参,形式上的参数,只是用来占位置var sum=0;for(var i=1;i<=num;i++){sum+=i;}console.log("从1到"+num+"的和为:"+sum);}//调用函数f2(99);//实参:实际上参与计算的参数f2(88);//定义带多个函数的参数function f3(start,end){//多个参数之间以逗号隔开var sum=0;for(var i=start;i<=end;i++){sum+=i;}console.log("从"+start+"到"+end+"的和为:"+sum);}//调用函数f3(20,30);f3(99,999);
提示: 分号是用来分隔可执行JavaScript语句。
由于函数声明不是一个可执行语句,所以不以分号结束。
2、函数的参数:
- 定义函数时指定的参数,称为
形参
,没有实际的值,占位置 - 调用函数时指定的参数,称为
实参
,有实际的值 - 实参个数和形参个数可以不同,未指定参数时其默认值为undefined
(1)
//实参的个数和形参的个数可以不一样function f1(a,b){console.log(a,b);console.log(arguments);//可以通过arguments获取所有实参}f1(2,5);f1(2);//未指定参数时其默认值为undefinedf1(2,5,6);//多余的参数没有任何影响
(2)
//同名函数,后定义的会覆盖前面定义的function f2(a){console.log(a);}function f2(a,b){console.log(a,b);}f2(6);
(3)
//函数与变量同名,变量会覆盖函数,即函数不生效function f3(){console.log("f3");}var f3="hello";f3();
(4)
//对函数的参数进行处理function f4(num1,num2){//只要不是数字,则默认设置为零if(isNaN(num1)){num1=0;}if(isNaN(num2)){num2=0;}console.log(num1+num2);}f4(2,7);f4("hello","world");f4(2);function f5(a,b){//如果参数为undefined、null、NaN,则默认设置为0if(typeof(a)!="string" && !a){a=0;}if(typeof(b)!="string" && !b){b=0;}console.log(a+b);}f5(2,7);f5("hello","world");f5(2,"");
3、函数的返回值:
- 函数执行后可以返回一个结果,称为函数的返回值
- 使用
return
关键字来返回函数执行后的结果值 - 如果函数中没有使用return返回值,则默认返回undefined
function f1(){var sum=0;for(var i=1;i<=100;i++){sum+=i;}return sum;//使用return关键字饭返回函数执行后的结果}var result=f1();//将函数的返回值存储到变量中console.log(result);console.log(result*2+6);//f1();可以不接收返回的返回值//如果函数没有使用return返回结果,则默认返回undefinedfunction f2(){console.log(111);}var result=f2();console.log(result);
//return的作用//1.计算两个偶数之和,如果传入的不是偶数,即立即停止function f3(a,b){//判断参数是否为偶数if(a%2!=0||b%2!=0){return;//停止函数的执行}var sum=a+b;console.log(sum);}f3(2,6);//2.计算从1到指定数字之和,最多只统计到数字7的总和function f4(num){var sum=0;for(var i=1;i<=num;i++){if(i>7){return sum;}sum+=i;}return sum;}var result=f4(5);console.log(result);
四、变量作用域
变量的作用域:
- 局部作用域
在函数中声明的变量,只能在该函数内访问,函数运行结束后变量自动销毁
- 全局作用域
在函数外声明的变量,或者在函数内未定义而直接赋值的变量,在任何位置都可以访问,将所在页面关闭后销毁
- 块级作用域
使用let
关键字声明的变量,只能在声明它的代码块内访问(使用var
声明的变量没有块级作用域的概念)
//全局作用域var name="tom";//全局变量,在任何位置都可以访问,当关闭页面时会自动销毁//局部作用域function f1(hobby){//函数参数也是局部变量,var age=18;//局部变量,只能在当前函数中访问,当函数执行结束后会自动销毁sex="female";//全局变量,未定义而直接赋值的变量console.log("f1:",name);console.log("f1:",age);console.log("f1:",sex);console.log("f1:",hobby);}function f2(){console.log("f2:",name);//console.log("f2:",age);//无法访问局部变量ageconsole.log("f2:",sex);}f1("健身");f2();console.log(name);//console.log(age);//无法访问局部变量ageconsole.log(sex);//块级作用域//在JavaScript新版本规范ES6中,提供了let关键字用来定义变量,作用与var类似if(true){var a=5;//全局变量let b=8;//块级变量,属于块级作用域,只能在当前代码块{}中使用console.log(a);console.log(b);}//代码块{var c=12;let d=14;}console.log(a);//console.log(b);//无法访问块级作用与变量bconsole.log(c);console.log(d);//无法访问块级作用与变量d
注意:
- 如果局部变量和全局变量同名,默认访问的是局部变量
- 如果想访问全局变量,必须使用
window
前缀,在一定条件下也可以使用this
前缀
//如果局部变量和全局变量同名,默认访问的是局部变量var x=5;function f3(){var x=8;console.log("局部变量:",x);console.log("全局变量:",window.x);console.log("全局变量:",this.x);//此处的this表示当前函数的调用者}//f3();window.f3();
五、变量提升
1、解析器执行JavaScript代码的过程:
1.首先预解析(全局作用域)
将变量var和函数function的声明提前到作用域的最上面,需要注意的是变量的赋值操作不会提前
2.然后执从上往下,一行一行执行代码
3.当执行函数时会进入函数内部,再次预解析 (局部作用域)
4.然后从上往下,一行一行执行代码
/*//思考一:undefinedvar num=10;fn();function fn(){console.log(num);var num=20;}*///第1步:预解析(全局作用域)var num;function fn(){//第3步:预解析(局部作用域)var num;//第4步:从上往下,一行一行执行代码console.log(num);//undefinednum=20;}//第2步:从上往下,一行一行执行代码num=10;fn();
/*思考二:undefined 9var a=18;f1();function f1(){var b=9;console.log(a);console.log(b);var a=77;}*///第1步:预解析(全局作用域)var a;function f1(){//第3步:预解析(局部作用域)var b;var a;//第4步:从上往下,一行一行执行代码b=9;console.log(a);//undefinedconsole.log(b);//9a=77;}//第2步:从上往下,一行一行执行代码f1();
/*思考三:f1();console.log(c);console.log(b);console.log(a);function f1(){var a=b=c=9;console.log(a);console.log(b);console.log(c);}*///第1步:预解析(全局作用域)function f1(){//第3步:预解析(局部作用域)var a;//局部变量a=b=c=9;//b和c是全局变量//var a=b=c=9;//等价于var a=9;b=9;c=9;//var a=9;b=9;c=9;//等价于var a=9;var b=9;var c=9;//第4步:从上往下,一行一行执行代码console.log(a);console.log(b);console.log(c);}//第2步:从上往下,一行一行执行代码f1();console.log(c);console.log(b);console.log(a);//a is not defined
2、区分:没有声明变量和变量未定义
/*区分:没有声明变量和变量未定义1.没有声明变量,报错:hobby is not defined2.声明了变量,但未赋值,结果:undefined*/console.log(hobby);//报错:hobby is not definedvar age;console.log(age);//undefined
六、定义函数的方式
两种方式:
- 函数声明
function f1(a,b){ return a+b;}console.log(f1(2,5));
- 函数表达式
var f2= function(a,b) // 等号右边的函数没有名字,称为匿名函数{ return a+b;
};
console.log(f2(3,6));//console.log(typeof f1);//function 函数也是一种数据类型
//console.log(typeof f2);//数据类型总结:string、number、boolean、null、undefined、object、function
两种方式的区别:
- 函数声明在编写时可以先调用,再声明
- 函数表达式必须先定义,再调用
七、 回调函数
不立即执行的函数调用,满足一定条件时才会执行或者由别的代码调用执行,称为回调函数 callback
调用时只写函数名,不能写小括号()和参数
应用:
- 作为事件绑定的函数,即当事件触发时要执行的函数
- 作为另一个函数的参数,即将函数作为参数传给另一个函数(函数也是一种数据类型)
//1.作为事件绑定的函数function f1(){console.log("天天开心");}//f1();//立即调用函数//当点击窗口时执行函数f1window.onclick=f1;//此时f1为回调函数,即回头再调用此函数,不能加小括号window.onclick=f1();//立即执行f1函数//2.作为另一个函数的参数function f2(args){if(typeof(args)!="function"){console.log(args);}else{args();//调用传入的函数}}var a=function(){console.log("你好");}f2(a);
八、匿名函数
没有名字的函数,称为匿名函数,一般用于回调
应用场景:
- 用于事件的回调
//一般用于回调window.onclick=function(){//匿名函数/回调函数,用于回调console.log("哈哈");//点击页面}
- 用于一次性执行的函数,会自动执行,称为自执行函数
/*//自执行函数,只会执行一次function f2(){console.log("嘻嘻");}f2();*/(function(a,b){console.log("嘻嘻",a,b);//匿名函数})(5,2)
- 将匿名函数作为另一个函数的参数
//将匿名函数作为另一个函数的参数var nums=[12,4,324,6,56];//nums.sort(function(a,b){//排序// return a-b;//});nums.forEach(function(value,index){//循环 value代表元素值本身,index代表索引console.log(index+"="+value);});
九、Debug调试
1. 简介
程序的故障和缺陷,称为bug
排除程序的故障和缺陷,称为debug
debug代码调试的方式:
- alert()
- console.log()
- 打断点,使用开发人员工具
2. 断点步骤
步骤:
- 设置断点(暂停执行的代码行 )
- 单步运行
- 观察变量