JS函数
- 函数
我们计算机语言里面的函数,不是数学的函数。跟数学的函数没关系。我们可以把JS中的函数理解为一个“盒子”,这个盒子里面装的是一段JS代码。当我们每次使用这个盒子的时候,就是在使用这个盒子里面的代码 - 函数的特点
a. 封装代码:使代码更加整洁
b. 重复使用:在重复使用的时候直接调用就好
c. 执行时机:随时可以在我们想要执行的时候执行 - 函数的创建(两种方式)
注意:函数创建完毕是不会执行的,只是做了一个函数放在内存中。就好比如你买了一个微波炉放在那,你不使用它它是不会给你加热的
a. 声明式函数:
语法:function 函数名( ) { }
释义:function是声明函数的关键字;空格,分隔关键字和函数名使用的;函数名,就是我们自定义的一个名字;( )里面填形参;{ }里面就是我们这个函数帮我们保存的一段 JS 代码
举例说明:
//声明式函数
function weibolu() {
// 下面就是叫做 weibolu 的这个函数里面封装的代码
console.log('我有加热功能')
}
b. 赋值式函数:
语法:var 函数名 = function ( ) { }
举例说明:
//赋值式函数
var bingxiang = function () {
// 下面就是叫做 bingxiang 的这个函数里面封装的代码
console.log('我有制冷功能')
}
- 函数的执行
一个函数创建出来后是不会自动执行的,需要我们来启动(调用)这个函数,那么函数里面的代码才会执行。我们有两种启动方式:
a. 直接执行:
语法:函数名( )
释义:函数名为你要调用的那个函数的名字,()里面填实参
b. 依赖事件执行
语法:指定页面元素.onclick = 函数名
释义:我们把这个函数依托在页面中某一个元素的事件上,当这个元素触发这个事件的时候,就会执行对应的函数
//例1:直接执行
function weibolu() {
console.log('我开始转转转 加热了')
}
var bingxiang = function () {
console.log('我开始呜呜呜 制冷了')
}
//当我们声明了上面两个函数,它们是不会执行的,我们现在需要启动(调用)它们才会执行
weibolu () //当这个代码执行的时候,weibolu 函数里面写的代码就会执行了
bingxiang () //当这个代码执行的时候,bingxiang 函数里面写的代码就会执行了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
div {
width: 100px;
height: 100px;
background-color: pink;
}
</style>
</head>
<body>
<!-- 例2:依赖事件执行 -->
<div id="kaiguan">微波炉的开关</div>
<script>
//准备一个微波炉函数
function weibolu () {
console.log('我开始转转转 加热了')
}
//把它绑定在 div 的点击行为上,这样点击页面上 id 为 kaiguan 的那个元素就会执行函数
kaiguan.onclick = weibolu
</script>
</body>
- 声明式函数与赋值式函数在调用上的区别
a.声明式函数可以在声明之前调用,也可以在声明之后调用
b.赋值式函数只能在声明之后调用,声明之前调用会报错
举例说明:
//声明式函数
//weibolu() 可以在此处调用
function weibolu() {
console.log('我开始转转转 加热了')
}
//weibolu() 也可以在此处调用
//赋值式函数
//bingxiang() 不能再此处调用,此处调用会报错
var bingxiang = function () {
console.log('我开始呜呜呜 制冷了')
}
//bingxiang() 只能在此处调用
- 函数的参数
①函数的参数分两种
a. 形参:
函数定义的时候写在小括号里面的内容。就是一个函数里面使用的变量,只不过这个变量的值由调用函数时的实参决定
b. 实参:
函数调用的时候写在小括号里面的内容。就是在调用函数的时候给形参进行赋值
②多个参数
a. 一个函数定义形参,理论上是可以写无限个的,不建议写太多(一般多的就是4个左右)。多个形参之间用逗号分隔
b. 一个函数调用的时候,理论上也可以给形参写无限个,不建议写太多,和形参一一对应,多个实参之间用逗号分隔
③参数是怎么储存的
当我们定义一个函数的时候,会在内存空间开辟一块空间。我们可以理解为一个“盒子”,这和盒子里面装的就是我们的JS代码。所有的形参,都是在这个内存空间中的一个一个的变量
举例说明:
//例1:
//定义一个函数
//小括号里面的 dongwu 就是形参,是一个还没有赋值的变量
function bingxiang(dongwu) {
console.log('我要呜呜呜 开始把 ' + dongwu + ' 冻起来')
}
//我们现在调用上面的函数
//本次调用的时候, 我给这个函数传递了一个实参
//就是给变量形参 bingxiang 赋值为 '大象' 这个字符串
bingxiang('大象')
//例2:多个参数
var bingxiang = function (dw1,dw2,dw3) {
console.log('我接收到了三个动物, 他们分别是 ' + dw1 + ' ' + dw2 + ' ' + dw3)
console.log('我只要把 ' + dw1 + ' 冻起来')
}
bingxiang('大象','长颈鹿','大熊猫')
//形参与实参之间是从左到右一一对应的
//'大象' 对应 dw1 '长颈鹿' 对应 dw2 '大熊猫' 对应 dw3
④参数的个数关系
a. 实参和形参一样多,实参和形参按照从左到右的顺序一一对应
b. 实参多,在函数内部会没有对应的形参来接收,我们不能直接使用。
c. 形参多,在函数内部多余出来的形参,没有对应的实参赋值,那么你在函数内部使用这个多出来的形参的时候就是 undefined ,是一个声明了,没有赋值的状态
var bingxiang = function (dw1,dw2,dw3) {
console.log('我接收到了三个动物, 他们分别是 ' + dw1 + ' ' + dw2 + ' ' + dw3)
console.log('我只要把 ' + dw1 + ' 冻起来')
}
bingxiang('大象','长颈鹿','大熊猫')
//三个形参 dw1 dw2 dw3
//从左到右一一对应三个实参 '大象' '长颈鹿' '大熊猫'
//如果只有两个形参 dw1 dw2
//还是三个实参 '大象' '长颈鹿' '大熊猫'(此时第三个实参会没有形参来接收)
//还是三个形参 dw1 dw2 dw3
//现在变成两个实参 '大象' '长颈鹿'
//此时形参 dw3 没有对应的实参进行赋值,如果在函数内部去使用它会是 undefined
- arguments
A. arguments 的释义:
每一个函数里面天生自带的一个变量,叫做 arguments 。你在函数里面不需要任何定义可以直接使用这个变量。它是一个数据的集合,保存了所有的实参。你传递一个实参,这里面就有一个数据;你传递十个实参,这里面就有十个数据。(所有实参的集合)
B. arguments 的使用:
①我们管 arguments 叫做 伪数组 或者 类数组
②有一个 length 属性,值就是这个 arguments 的长度。这个 arguments 里面有多少个数据,这个 arguments 的 length 就是几
③arguments 里面是按照顺序把所有的实参排列好,我们管这个顺序叫做 索引 或者 下标。索引和下标是一个官方的名字,其实就是数据的序号。索引(下标)是从 0 开始的,按照 +1 的顺序递增
④我想从 arguments 里面获取某一个数据可以通过索引(下标)来获取数据
举例说明:
function fn () {
console.log(arguments)//因为传递了两个实参,那么 arguments 中就有两个数据 分别是 10 20
console.log(arguments.length)//两个实参,那么长度为2
console.log(arguments[0])//第一个数据的索引(下标)为0 ,此处打印出来的是10
console.log(arguments[1])//第二个数据的索引(下标)为1 ,此处打印出来的是20
}
fn(10,20)//传递两个实参,分别为 10 20
- 函数的返回值(return)
①释义:一个函数的结果,我们专业名称叫做 返回值。我么哪一个函数的结果叫做这个函数的返回值,我们函数内部的返回值使用 return 来表示
举例说明:
//一个函数
function bingxiang(dw) {
console.log('10min later')
console.log('20min later')
var str = '冰' + dw + '冰冰'
return str//函数的返回值就是这个 str 的值
}
//调用函数
//当你调用一个函数的时候, 函数里面的代码会从上到下的执行一遍
//函数的返回值, 我们直接在函数前面定义变量接收
// result 接收到的内容就是 bingxiang 这个函数里面 return 的内容
var result = bingxiang('大象')
②函数的返回值(return)可写可不写。如果一个函数内部没有 return ,那么这个函数就没有返回值,你要是非要接收返回值就是 undefined;如果一个函数内部写了 return,没有写内容,那么也是没有返回值,你要是非要接收返回值就是 undefined;如果一个函数内部写了 return ,后边也写了内容,你写的内容就是函数的返回值,你在外部接收到的就是这个东西
③return 的第二个功能:return 除了可以给函数一个返回值之外,还有一个功能就是打断函数的继续执行。当函数内部的代码执行到 return 之后,return 后面的所有代码都不在执行了,直接结束函数。(注意:函数内部的打断不是 break ,是 return)
举例说明:
function fn(dw) {
console.log(1)
console.log(2)
console.log(3)
return 123// 当代吗遇到这个 return 的时候,直接结束函数,并给出一个返回值
// 此时的返回值是 123
console.log(4)
console.log(5)
}
var res = fn() //调用这个函数,并把函数的返回值赋值给 res
console.log(res) //控制台打印这个函数的返回值
- 作用域
①释义:一个变量的使用范围(能生效的区域)
②作用域的分类
a. 全局作用域:
当你打开一个页面的时候,就是一个全局作用域生成了,通篇的代码都是存在全局作用域里面的
b. 局部作用域(私有作用域/函数作用域):
只有函数生成私有作用域!!!当函数定义过后,不需要调用,作用域就确定好了
③作用域的上下级关系
当代码书写好了以后, 作用域就已经生成了,你的函数写在哪一个作用域里面, 这个函数就是哪一个作用域的子级
举例说明:
console.log('a')//这个代码是在全局作用域里面
function fn1() {
//fn1的这个大括号里面就是一个叫做 fn1 的私有作用域
function fn3() {
//这个大括号里面就是一个叫做 fn1 的私有作用域 里面的 fn3 私有作用域
}
}
function fn2() {
// 这个大括号里面, 就是一个叫做 fn2 的私有作用域
}
示意图理解:
10. 在作用域里面定义变量
我们在哪个作用域里面书写的变量,这个变量就是属于哪个作用域。这个变量只能在这个作用域范围内使用,或者在这个作用域的下级作用域内使用,不能在这个作用域的上级作用域内使用
举例说明:
var n1 = 100//这个 n1 变量就是一个全局作用域内的变量 ,叫做全局变量,
//可以在全局作用域, 以及全局作用域下的所有后代作用域使用
// 这个 fn 也是一个变量名(函数名)
// fn 这个变量也是可以在全局作用域下使用
function fn() {
var n2 = 200 // 这个 n2 变量就是一个私有作用域内的的变量,叫做私有变量
// 只能在 fn 这个作用域内部使用, 在 fn 的所有后代作用域里面使用
// 在全局里面使用不了
console.log(n2) // 可以的
console.log(n1) // 可以的
}
// console.log(n2) // 这里使用不了,因为 fn 是 全局作用域的下级作用域