js05
目录
前言
day20-js第五天学习开始
一、函数
- 函数:是一些预先设定好的功能集合,可以在需要的时候重复执行
- 函数分为系统函数和自定义函数
- 系统函数:Numder() parseInt() parseFloat()
- 自定义函数:laba() getSum() getMax(a,b)
1.1创建自定义函数的格式
function 函数名称(参数列表){ 函数体(每次调用函数时,重复执行的代码) }
- 函数名定义时需要遵循起名规则
- 函数需要调用才可以执行,调用格式: 函数名称(参数列表)
1.2创建带有参数的自定义函数
function 函数名称(参数列表){//形参,用于接收外部传递过来的值 函数体 }
- 调用带有参数的函数:函数名称(参数列表)//实参,调用函数时给函数传递的具体的值
- 创建函数时参数列表中的变量称为形参,调用函数时传入的值叫做实参,实参的值会赋值给形参
- 形参与实参的数量可以不匹配,但是这个不推荐
- 如果形参未被赋值,则值为undefined
- 如果实参的个数大于形参的个数,以形参个数为准,剩余的实参无效
1.3创建带有返回值的自定义函数
function 函数名称(参数列表){ 函数体 return 要返回的结果 }
- 调用函数的格式: var 变量 = 函数名称(参数列表)
注意:我们可以定义变量来保存函数执行后返回的结果,也可以做打印或者其他的进一步操作
- return用于返回函数执行后的结果
- 外部想要获取到函数return的结果,需要调用函数
- 如果函数没写return或return后没有值,返回的结果是undefined
- return后的代码不执行,原因:一旦遇到return,函数会直接结束
function fun(){ console.log(666)//我是函数的具体功能 return 999//我是函数的返回值 } //先执行fun()的功能打印666,再将fun()的返回值999拼接打印 console.log('我是54行'+fun()) var f = fun()//定义变量来保存fun()返回的结果999 console.log('我来保存函数返回的结果'+f)
1.4return和break
- return用于函数中,结束函数的调用并返回结果
- break用于循环和switch-case,结束单层循环或者是switch-case语句
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>函数的返回值</title> </head> <body> <script> //练习:创建函数getMax2,传递三个数字,返回最大值 function getMax2(a, b, c) { //方案1:使用分支结构 // if(a>b && a>c){ // return a // }else if(b>c){ // return b // }else{ // return c // } //方案2:使用三目运算符实现 return a > b && a > c ? a : (b > c ? b : c) } var r = getMax2(520, 888, 999) console.log(r) //练习:创建函数getCountry,传递任意一个数字,返回对应的国家 //1-中国 2-法国 3-英国 其他-八宝山 //使用switch-case结构完成 function getCountry(a) { switch (a) { case 1: return '中国' break //添加break为了防止穿透 case 2: return '法国' break case 3: return '英国' break default: return '八宝山' } } var r2 = getCountry(3) console.log(r2) //练习:创建函数isRun,传递任意一个年份,判断是否为闰年,返回一个布尔型的结果 function isRun(year) { //方案1: /* if (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0) { return true } return false */ //方案2: //return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0 ? true : false //方案3:三目运算符中1号位置的结果本来就是布尔类型的结果,所以可以这么写 return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0 } console.log(isRun(2021)) </script> </body> </html>
二、 变量的作用域
- 全局作用域: 在函数以外的作用域,只有一个全局作用域
- 函数作用域:在函数以内的作用域,可能有多个函数作用域
- 全局变量:在全局作用域下声明的变量,可以在任意作用域下访问到
- 局部变量:在函数作用域下声明的变量,只能在所在的函数作用域访问到
- 在函数内,不加var声明的变量是全局变量
注意:这只是一种特殊现象,我们定义全局变量时,还是要按照规范语法来写
- JS的预加载/预解析:
- 在程序执行前,会将用var声明的变量提升到所在作用域的最前面
- 但注意:只提升声明部分,赋值不提升
- 其他规则:
- 变量查找规则:就近原则,当前作用域下有的就不再向全局作用域下查找
- 形参属于局部变量,只能在函数内访问
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>变量的作用域</title> </head> <body> <script> //全局作用域:函数以外的作用域,只有一个 //全局变量:在全局作用域下声明的变量 var a = '北京市城管' function shiJS(){ //函数作用域:在函数以内的作用域 //局部变量:在函数作用域下声明的变量,只能在所在的函数作用域生效 var b = '石景山城管' console.log(b)//局部作用域下可以使用自己的局部变量 console.log(a)//局部作用域下也可以使用全局变量 } shiJS() console.log(a)//全局作用域下可以使用全局变量 //console.log(b)//报错,局部变量不可以在全局范围用 function haiD(){ var c = '海淀城管' console.log('海淀区~~~') console.log(c)//海淀城管 console.log(a)//北京市城管 console.log(b)//报错,不能在函数作用域下使用其他作用域的局部变量 } //haiD() console.log(a)//全局作用域下可以使用全局变量 //console.log(c)//局部变量不可以在全局范围使用 //思考: var n1 = 2 function fn(){ n1 = 4//给上面已经定义好的全局变量n1重新赋值为4 var n2 = 5 n3 = 6//在函数内,不加var声明的变量是全局变量 } fn() console.log(n1)//4 //console.log(n2)//报错,局部变量无法在全局范围内访问 console.log(n3)//6 </script> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>作用域练习</title> <style> div { width: 100px; height: 28px; background-color: lightgreen; } </style> </head> <body> <div id="box"> <button id="btn1">变长</button> <button id="btn2">变短</button> </div> <script> //练习:定义一个宽高为100*28像素的div,背景颜色为浅绿色 //再定义两个按钮,用户点击"变长"按钮,div的宽度增加5px //用户点击"变短"按钮,div宽度减少5px //1.定义全局变量用来保存div的宽度 var a = 100 //2.给"变长"按钮添加点击事件 btn1.onclick = function(){ a += 5//每次点击按钮,div总宽度+5 console.log(a) box.style.width = a+'px' } //3.给"变短"按钮添加点击事件 btn2.onclick = function(){ a -= 5 box.style.width = a+'px' } /* //练习:查看以下程序的输出结果 function fun(){ m3 = 5 //没加var声明,是全局变量 m2 = m3//m2也是全局变量 var m1 = m2//m1是局部变量 var m1 = m2 = m3 = 5//这样写只有m1是带var的,也就是说m1是局部变量 var m1,m2,m3 = 5//这是同时声明了3个局部变量,用逗号隔开相当于3个变量都带var } fun() console.log(m3)//5 console.log(m2)//5 console.log(m1)//报错,局部变量无法在全局范围内使用 */ </script> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>变量的作用域2</title> </head> <body> <script> /* var a = 1 console.log(a)//1 //在打印语句之前,明明没有b变量,为什么没有报错? //在程序执行之前,会将用var声明的变量提升到所在作用域的最前面 //但注意,只提升声明部分,赋值不提升 //var b--这句代码不是真实存在的,为了辅助变量提升的理解 console.log(b)//undefined var b = 1 console.log(c)//报错,引用错误,变量c没有定义 c=1 //没有使用var定义c变量,所以不存在变量提升的现象 */ //思考1:这两句的打印结果是什么? function f1(){ console.log(d) //undefined,变量提升,声明但未赋值 var d = 3 console.log(d)//3,局部变量声明且赋值,打印出来具体的值 } f1() //思考题2:这两句的打印结果是什么? var e = 4 function f2(){ //变量的查找原则:就近原则,当作用域下有就不再向全局作用域下查找 //var e -->变量提升的代码 console.log(e)//undefined,变量提升+就近原则 var e = 5 console.log(e)//5,使用局部变量 } f2() //思考题3:这两句代码的执行结果是什么? function f3(x){ var x = 2 console.log(x) } f3(33) //console.log(x)//报错,形参是局部变量,不可以在全局范围内使用 //思考题4:这两句代码的执行结果是什么? var y = 7//全局变量 function f4(y){ y+=3//让形参(局部变量的值+3) console.log(y)//8=实参5+3 } f4(5) console.log(y)//7,使用的是全局变量的值 </script> </body> </html>
三、函数的作用域
- 全局函数:在全局作用域下创建的函数,可以在任何作用域下调用
- 局部函数:在函数作用域下创建的函数,只能在当前函数作用下调用
- 作用域链:作用域之间嵌套形成的作用域结构
- 在查找变量的时候,先在当前作用域下查找,如果没有会沿着作用域链向上一级级不断查找
- 函数提升:程序执行之前,会将函数整体提升到所在作用域的最前面
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>函数的作用域</title> </head> <body> <script> //定义全局函数 function fn1(){ console.log('哈哈哈哈我是一个全局函数') } fn1() //调用全局函数 //1.定义全局函数 function fun(){ console.log('我是全局函数fun()') //2.定义局部函数 function fun2(){ console.log('我是局部函数fun2()') } //4.在函数作用域下调用局部函数 fun2() } //3.调用全局函数fun() fun() // fun2()//错误,局部函数不可以在全局调用 //作用域链:作用域之间嵌套形成的作用域结构 //在查找变量的时候,先在当前作用域下查找,如果没有会沿着作用域链往上一级级不断查找 var a = 1//1.定义全局变量 function zoo(){//2.定义全局函数 var a = 2//3.定义了局部变量 function zoo2(){//4.定义局部函数 console.log(a)//2,有局部变量打印局部变量的值,没有局部变量使用全局变量的值 } zoo2()//5.调用局部函数 } zoo()//6.调用全局函数 //函数提升:程序执行之前,会将函数整体提升到所在作用域的最前面 foo()//999 function foo(){ console.log(999) } </script> </body> </html>
四、匿名函数
没有名字的函数 function (参数列表){函数体}
4.1创建函数
函数声明:--创建有名字的函数
function fn(){ 函数体 }
- 函数表达式:--创建匿名函数
var fun = function(){ 函数体 }
把匿名函数赋给一个变量,变量名称就是函数名称
4.2对比函数名称和函数名称()
函数名称,本质上是一个变量,变量中保存了一个函数类型的值
- 函数名称(),是在调用函数,执行函数体中的代码
4.3对比函数声明和函数表达式区别
函数声明: 存在函数的整体提升,可以先写调用再写创建
- 函数表达式:只是存在声明提升,必须先写创建再写调用
注意:函数本身也是一个值,类型function—这是我们遇到的第6种类型,函数类型属于引用类型
4.4函数示例
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>匿名函数</title> </head> <body> <script> //之前创建函数的方式--函数声明 function fn() {} //函数是有名字的fn //创建匿名函数--函数表达式 //把匿名函数赋给一个变量,变量名称就是函数名称 //可以说fun变量保存了一个匿名函数,同时变量名称fun就可以看做是这个匿名函数的名称 var fun = function() { console.log('我是一个匿名函数') } console.log(fun) //f (){ } console.log(typeof fun) //function 函数类型 console.log(fn) console.log(typeof fn) //function 函数类型 //练习:使用函数表达式创建函数getSum,传递任意两个数字 //返回两者之间所有整数的和 //var getSum变量提升只提升声明部分,不提升赋值 console.log(getSum(100,1))//报错,类型错误,原因是匿名函数只有声明提升 var getSum = function(n1, n2) { //在循环之前,如果n1>n2,需要交换两个变量的值 //我们要把小的数字作为循环的起始值 if(n1>n2){ var c = n1 n1 = n2 n2 = c } console.log(n1,n2)//打印两个变量交换以后的值 //循环n1~n2之间所有的整数 for (var i = n1, sum = 0; i <= n2; i++) { sum += i//累加 } return sum } //使用匿名函数的方式与之前的方式相同,getSum变量就相当于是匿名函数的名字 //console.log(getSum(100,1)) </script> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>绑定事件处理函数</title> </head> <body> <button id="btn">按钮</button> <button id="btn2">按钮</button> <script> btn.onclick = function(){//这是之前使用点击事件 alert('按钮被点击了') } var fun = function(){//fun变量用于保存匿名函数 alert('fun被调用了') } var fn = function(){//fn变量用于保存匿名函数 alert('fn被调用了') } //只要一点击按钮,就会找到fun变量所保存的匿名函数,执行匿名函数的功能 // btn2.onclick = fun btn2.onclick = fn </script> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>递归案例</title> </head> <body> <script> //定义变量,用于保存用户输入的数字 //求用户输入数字对应的阶乘结果 //5!=5*4*3*2*1=120 //4!=4*3*2*1 //3!=3*2*1 //2!=2*1 //1!=1--数学公式 //f(5)=5*4*3*2*1=5*f(4) //f(4)=4*3*2*1=4*f(3) //f(3)=3*2*1=3*f(2) //f(2)=2*1=2*f(1) //f(1)=1 //递归:1.总结规律 2.最简问题 //规律:f(n)=n*f(n-1) 最简问题:f(1)=1 function f(n){//--功能求递归函数 if(n===1){//最简问题 return 1 }else{ //递归:在方法内部自己调用自己 return n*f(n-1)//找到的规律 } } console.log(f(5)) </script> </body> </html>
五、练习
练习:创建函数isPrime,传递任意一个数字,查看是否为素数,返回一个布尔型的结果
- 打印出101~200之间所有的素数
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>day20作业答案</title> </head> <body> <script> //创建函数isPrime,传递任意一个数字,查看是否为素数,返回一个布尔型的结果 function isPrime(n) { //console.log('素数判断逻辑开始:') //如果n小于或等于1,则不是素数 if (n <= 1) { return false } //循环获取2~n-1之间所有的整数 for (var i = 2; i < n; i++) { //i表示从2~n-1之间所有的整数 //判断当前循环到的数字能否被n整除 if(n%i === 0){//如果可以整除,说明n不是素数 return false//返回false结果 } } //如果n不是素数,这句不会打印,因为上面的return会提前结束程序 //console.log('素数判断逻辑结束:') //循环结束能走到这里,说明刚刚循环的2~n-1所有数字均不可以被n整除,n是素数 return true//返回true结果 } // var r = isPrime(8)//调用函数,并将函数return的结果保存在r变量中 // console.log(r) // console.log(isPrime(8))//先调用函数的功能,再直接打印函数return的结果 //打印出101~200之间所有的素数 //1.循环101~200之间所有的整数 //2.使用刚刚写好的自定义函数isPrime(n)来判断是否为素数 //3.如果是素数,打印出来 for(var i = 101 ; i <= 200 ; i++){ //i代表我们循环到的每个整数 if(isPrime(i)){//如果是素数,isPrime()的结果是true console.log(i)//是true就会打印出来当前循环到的数字 } } </script> </body> </html>
总结
day20-js05学习结束