一、简介
函数是用来完成特定功能的代码块,可以被调用执行多次,实现复用
分类:
- 内置函数
- 自定义函数
二、内置函数
函数名 | 含义 |
---|---|
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);//未指定参数时其默认值为undefined
f1(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,则默认设置为0
if(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返回结果,则默认返回undefined
function 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);//无法访问局部变量age
console.log("f2:",sex);
}
f1("健身");
f2();
console.log(name);
//console.log(age);//无法访问局部变量age
console.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);//无法访问块级作用与变量b
console.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.然后从上往下,一行一行执行代码
/*//思考一:undefined
var num=10;
fn();
function fn(){
console.log(num);
var num=20;
}*/
//第1步:预解析(全局作用域)
var num;
function fn(){
//第3步:预解析(局部作用域)
var num;
//第4步:从上往下,一行一行执行代码
console.log(num);//undefined
num=20;
}
//第2步:从上往下,一行一行执行代码
num=10;
fn();
/*思考二:undefined 9
var 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);//undefined
console.log(b);//9
a=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 defined
2.声明了变量,但未赋值,结果:undefined
*/
console.log(hobby);//报错:hobby is not defined
var 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();//立即调用函数
//当点击窗口时执行函数f1
window.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. 断点步骤
步骤:
- 设置断点(暂停执行的代码行 )
- 单步运行
- 观察变量