函数的概念
首先一定要明确,和数学中的函数完全是两回事
在JS中,函数可以理解为 一段在程序(页面)中多次出现的代码段 封装起来的盒子
简单来说,JS的函数就是一个盒子,盒子里边装的是 在当前页面中 多次出现的 较为复杂的代码段
这5行代码模拟一个较为复杂的功能,它们5个必须在一起才能正常执行
console.log(100)
console.log(100)
console.log(100)
console.log(100)
console.log(100)
函数的使用
1.函数的定义(创建一个盒子)
1.1声明式定义
语法:function fn(){}
function:关键字->表明后续的是一段函数
fn:函数的名字->将来函数调用的时候需要用到,函数名自定义
():内部填写参数->欠着,后续详细的讲解
{}:内部填写函数调用时要执行的代码段
1.2赋值式定义
语法:var fn=function(){}
2.函数的调用 (使用盒子内的代码)
不管是声明式还是赋值式定义的函数,调用方式都是一样的
调用语法:函数名()/变量名()
声明式与赋值式的区别
1)写法不同
2)调用上略有不同
声明式定义的函数可以在函数定义前去调用
赋值式定义的函数不能在函数定义前去调用
赋值式定义的函数不能在函数定义前去调用的原因:
赋值式定义,其实就是声明一个变量,然后给它赋值为一个函数
在JS中,如果在定义变量之前使用变量的话,那么变量的值为undefined (变量提升 面试可能会问)
函数的执行结果,一般默认都是undefined 除非手动更改
函数的参数
函数的参数如何书写?--- 书写在function后的小括号内
参数的作用
如果一个函数没有书写参数,那么这个函数的功能相对单一。
如果书写了参数,能够使我们这个函数的使用更加灵活。
参数的书写
(1)function后的小括号内书写的参数叫做 “形参”!!!
形参的作用:书写之后,相当于在函数内部创建了一个变量,变量实际的值由“实参”传递。
(2)函数名后的小括号内书写的参数叫做“实参”!!!
实参的作用:将自身的值按照一一对应的关系传递给形参。
函数参数的默认值
函数在创建形参的时候,默认给一个值,将来在调用函数的时候,如果没有传递 那么这个形参的值也不会是undefined 而是给的默认值。
如果传递了对应的值,那么形参的值是实参传递进来的值,否则按照默认值来运行。
函数的返回值
(函数的执行结果)
JS有一个规定:在函数内部创建(定义)的变量,只能在函数内部使用,后续学习作用域的时候,会详细讲解
我们如果想在函数外部得到函数内部的某一个值,或者是运算结果,我们可以通过return这个关键字来帮我们完成
return的注意事项: return具有中断函数的能力,所以一般来说我们将它放在函数的尾部。
函数的预解析
预解析的一个表现就是 声明式函数再定义前可以被调用
预解析是什么?
JS在执行代码的时候,会有一个所谓的解析阶段
解析阶段,做了一件事,就是函数提升,就是将声明式函数的定义,提升到当前作用域的最顶端。
作用域的最顶端:暂时理解为当前页面的最开始的位置
浏览器会对我们的JS代码,做一个预解析,预解析的时候,会将函数提升到当前作用域的最顶端(暂时理解为当前页面最开始的位置)
<script>
fn() //这行代码是函数调用,所以不需要提升
function fn() {//这是一个声明式定义的函数,所以需要提升
console.log('我是fn函数,我被调用了')
}
// 预解析之后的代码(执行顺序):
function fn() {
console.log('我是fn函数,我被调用了')
}
fn() //所以此时调用的时候,因为fn函数已经定义完成了,所以这里能够正常执行函数
</script>
作用域
什么是作用域?--- 变量可以起作用的范围
作用域分为两个
1.全局作用域
直接在script内书写的代码)
在此作用域创建的变量,我们叫做全局变量,在当前script标签内的哪里都能使用
在JS中,全局作用域中,有一个提前给我们准备好的对象(一种数据格式,后续会详细讲解) 这个对象叫做window
2.局部作用域
(在JS中,只有函数能够创建局部作用域)
在此作用域创建的变量,只能在当前作用域使用,超出这个作用域(也就是在函数外边)去使用,就会找不到变量
作用域链
(这是一个纯概念性的东西,面试也可能会问)
作用域就是在访问一个变量的时候,如果当前作用域内没有,会去自己的父级作用域,也就是上一层作用域内查找,如果找到直接使用,如果没有找到继续向上层查找
直到查到最顶层的作用域,如果找到了直接使用,如果没找到,报错提示变量不存在(未定义)
我们将这个一层一层向上查找的规律,叫做作用域链
作用域链的赋值规则
在给变量赋值的时候,首先会去当前作用域内查找该变量,如果有,直接赋值;
如果没有,会去自己的父级查找,在父级找到直接修改值然后停止查找,如果没有继续向自己的父级查找,知道知道全局作用域
在全局作用域内,知道直接赋值修改他的值,如果没有找到,那么在全局作用域创建一个变量,并赋值
递归函数
本质上还是一个函数
当一个函数在函数的内部调用了自身,那么就算是一个所谓的递归函数(只不过有点小缺陷)