五、函数封装及调用、参数及返回值、作用域、匿名函数、立即执行函数
1. 函数基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
span {
display: inline-block;
width: 70px;
border: 1px solid lightcoral;
padding-left: 5px;
}
</style>
</head>
<body>
<!--
函数: 是可以被重复使用的代码块
作用:把具有相同或相似逻辑的代码“包裹”起来,有利于代码复用
-->
<!-- alert(),parseInt()都是函数的调用 -->
<script>
/* for (let j = 1; j < 10; j++) {
for (let i = 1; i <= j; i++) {
document.write(<span>${i}*${j}=${i * j}</span>)
}
document.write('<br>') //换行标签
} */
// 封装九九乘法表
function jiujiu() {
let strI = ''
for (let i = 1; i <= 9; i++) {
let strJ = ''
for (let j = 1; j <= i; j++) {
strJ += `<span>${j}×${i}=${j * i}</span>`
}
strI += `<p>${strJ}</p>`
}
document.write(strI)
}
// 调用函数
jiujiu()
jiujiu()
</script>
</body>
</html>
2. 函数参数及返回值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 声明函数时小括号里的叫形参 → 接收数据用
function sum(a, b) {
// 想要把函数内部的计算结果拿到函数外面使用,就需要返回值
// 返回值 返回的位置是函数调用的位置
// return退出当前函数 下方代码不执行
// 函数可以没有 return,这种情况函数默认返回值为 undefined
return a + b
}
// 调用函数时小括号里的叫实参 → 真实数据
// 若函数无返回值,输出函数调用得到的结果为undefined
console.log(sum(1, 2))
</script>
</body>
</html>
3. 参数注意事项
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function fn(stuID, name, age) {
console.log(stuID, name, age)
/* console.log(typeof stuID)
console.log(typeof name)
console.log(typeof age)
console.log('----------') */
}
fn(1, 'Tom', 18) // 1 'Tom' 18
// 传入数据顺序错误,不报错
fn('Tom', 1, 18) // Tom 1 18
// 开发中尽量形参和实参个数保持统一
// 如果形参过多 会自动填上undefined
fn(1, 'Tom') // 1 'Tom' undefined
// 如果实参过多 那么多余的实参会被忽略
fn(1, 'Tom', 18, 80) // 1 'Tom' 18
</script>
</body>
</html>
4. 逻辑中断
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// || 或 一真则真,左边true右边中断
function sum(x, y) {
// console.log((x || 0) + (y || 0))
x = x || 0
y = y || 0
console.log(x + y)
}
sum() // 0
sum(1) // 1
sum(2, 2) // 4
</script>
</body>
</html>
5. 默认参数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 计算100+用户输入的数字
// 默认值:只会在缺少实参传递或者实参是undefined才会被执行
// 函数定义时,默认参数放到必须传参的形参后边
function sum(x, y = 0) {
console.log(x + y)
}
sum(100) // 100
sum(100, 20) // 120
</script>
</body>
</html>
6. 数组求和
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 函数封装-数组求和
function arrSum(arr) {
let sum = 0
for (let i = 0; i < arr.length; i++) {
sum += arr[i]
}
return sum
}
// console.log(arrSum([1, 2, 3, 4, 5])) // 15
// 用户输入的数字做累加
let arr = []
for (i = 1; ; i++) {
let num = +prompt(`
请输入数字${i}
输入666则退出输入
`)
if (num === 666) {
break
} else {
arr.push(num)
}
}
console.log(arrSum(arr))
</script>
</body>
</html>
7. 任意数组最大最小值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- <script>
//封装函数,求任意数组的最大值
function getMax(arr) {
let max = arr[0]
for (let i = 1; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i]
}
}
console.log(max)
}
getMax([1, 23, 34, 6, 7, 8])
</script> -->
<!--
debugger
通过代码打断点,看完执行流程需要手动注释代码
-->
<!--
1. 封装函数,求任意数组中的最大值并返回这个最大值
2. 封装函数,求任意数组中的最小值并返回这个最小值
-->
<script>
// 最大值
// arrMax(arr)中的arr为形参 使得这个函数的灵活性更高
function arrMax(arr) {
let max = arr[0]
for (let i = 1; i < arr.length; i++) {
max = max > arr[i] ? max : arr[i]
}
return max
}
console.log(arrMax([1, 2, 5, 8, 12, 35, 34]))
// 最小值
function arrMin(arr) {
let min = arr[0]
for (let i = 1; i < arr.length; i++) {
min = min < arr[i] ? min : arr[i]
}
return min
}
console.log(arrMin([1, 2, 5, 8, 12, 35, 34]))
</script>
</body>
</html>
8. 判断数组是否存在某个元素 some
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 封装函数,判断数组是否存在某个元素,
如果有则返回true,否则返回false -->
<!--
①:函数封装 some,传递两个参数:元素和数组
②:可以设置一个初始变量 flag 为 false
③:如果能找到,则修改 flag 值为 true,则中断循环,找不到则不修改 flag
④:返回 flag
-->
<script>
function some(arr, num) {
let flag = false
for (let i = 0; i < arr.length; i++) {
if (arr[i] === num) {
flag = true
break
}
}
return flag
}
console.log(some([1, 2, 4, 7, 24, 47, 56], 100))
console.log(some([1, 2, 4, 7, 24, 47, 56, 100], 100))
</script>
</body>
</html>
9. 查找元素在数组中的索引 findIndex
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!--
封装函数,查找元素在数组中的索引l。
如果找到该元素(第一个元素即可),则返回该元素的索引号,找不到该元素则返回-1
思路:
①:函数封装findlndex,传递两个参数:元素和数组
②:可以设置一个初始变量 index 为-1
③:如果能找到,则修改index值为当前索引号,则中断循环,找不到则不修改index
④:返回index
-->
<script>
let names = ['小红', '小明', '大强']
function findIndex(e1, arr = []) {
let index = -1
for (let i = 0; i < arr.length; i++) {
if (arr[i] === e1) {
index = i
break
}
}
return index
}
console.log(findIndex('小明', names))
</script>
</body>
</html>
10. 作用域
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 作用域:变量或者值在代码中可用性的范围 -->
<!-- 作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。 -->
<!--
1. 全局作用域 script 标签或者js文件 → 全局变量
2. 局部作用域 函数作用域和块级作用域{} → 局部变量
块级作用域{}(let const)
-->
<!--
注意:
函数内部不声明直接赋值的变量当全局变量,不提倡
函数内部的形参可以当做局部变量看
-->
<script>
let num = 10
console.log('函数外', num)
function fn() {
// 先使用后调用 报错
console.log('函数内', num)
let num = 100
}
fn()
// 作用域链(就近原则)
/*
在函数被执行时,会优先查找当前函数作用域中查找变量
如果当前作用域查找不到则会逐级向上查找父级作用域直到全局作用域
都找不到则提示错误,这个变量没有被定义过
*/
</script>
</body>
</html>
11. 匿名函数
11.1 函数表达式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 有名函数 → 具名函数 -->
<!--
匿名函数 function(){}
两种使用方式:函数表达式、立即执行函数
-->
<script>
/*
函数表达式:将匿名函数赋值给一个变量,并且通过变量名称进行调用
函数表达式必须先定义,后使用
*/
let fn = function () {
console.log('匿名函数')
}
fn()
</script>
</body>
</html>
11.2 立即执行函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!--
立即执行函数,避免全局变量之间的污染
注意:多个立即执行函数要用 ; 隔开,要不然会报错
立即执行函数可以传参,立即执行函数可以添加函数名
-->
<!-- JS写分号代表结束 -->
<script>
// 1. (匿名函数)()
(function () {
console.log('(匿名函数)()')
})();
// 2. (匿名函数())
(function () {
console.log('(匿名函数())')
}());
</script>
</body>
</html>
12. 案例-手风琴
重要代码第85行
<!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>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
display: flex;
justify-content: space-around;
flex-direction: column;
align-items: center;
height: 100vh;
padding: 0 20px;
}
.one {
width: 760px;
height: 260px;
border: 1px solid #000;
}
.two {
width: 640px;
height: 260px;
border: 1px solid #000;
}
.box {
display: flex;
overflow: hidden;
height: 260px;
}
.box>div {
width: 120px;
border: 1px solid #fff;
transition: all 0.5s;
}
.box>div:hover {
width: 400px;
}
</style>
</head>
<body>
<div class="container">
<div class="one">
<!-- <div class="box">
<div><img src="./images/1.jpg" alt=""></div>
<div><img src="./images/2.jpg" alt=""></div>
<div><img src="./images/3.jpg" alt=""></div>
<div><img src="./images/4.jpg" alt=""></div>
<div><img src="./images/5.jpg" alt=""></div>
<div><img src="./images/6.jpg" alt=""></div>
<div><img src="./images/7.jpg" alt=""></div>
</div> -->
</div>
<div class="two"></div>
</div>
<script>
let arr = [
'./images/1.jpg',
'./images/2.jpg',
'./images/3.jpg',
'./images/4.jpg',
]
let arr2 = [
'./images/5.jpg',
'./images/6.jpg',
'./images/7.jpg',
]
function getAccordion(array) {
let str = ''
for (let i = 0; i < array.length; i++) {
str += `<div><img src="${array[i]}" alt=""></div>`
}
return `<div class="box">${str}</div>`
}
document.querySelector('.one').innerHTML = getAccordion(arr)
document.querySelector('.two').innerHTML = getAccordion(arr2)
</script>
</body>
</html>
13. 作业
13.1 封装 everyLessThan 函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!--
用于检测数组所有元素是否都满足小于某个数值
-->
<script>
// 1. everyLessThan 函数声明
function everyLessThan(arr = [], num) {
// 补充代码
let elt = true
for (let i = 0; i < arr.length; i++) {
if (arr[i] >= num) {
elt = false
break
}
}
return elt
}
// 2. everyLessThan 函数的调用
console.log(everyLessThan([10, 20, 30], 25)) // false
console.log(everyLessThan([1, 2, 3], 5)) // true
</script>
</body>
</html>
13.2 封装求和或平均值函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!--
函数可以传递 2 个参数,比如 sumOrAvage(arr, true)
参数一: 接受实参传递过来的数组
参数二: 布尔类型
如果是true或者不传递参数 是求和操作
如果传递过来的参数是 false 则是求平均值
sumOrAvage 函数内,将计算的结果进行返回
-->
<script>
function sumOrAvage(arr = [], isSum) {
let sum = 0
for (let i = 0; i < arr.length; i++) {
sum += arr[i]
}
if (isSum !== false) {
return sum
} else {
return sum / arr.length
}
}
// 第二个参数布尔值true,表示求和
console.log(sumOrAvage([1, 2, 3], true)) // 6
// 第二个参数不传,也是默认求和
console.log(sumOrAvage([1, 2, 3])) // 6
// 第二个参数布尔值false,表示求平均值
console.log(sumOrAvage([1, 2, 3], false)) // 2
</script>
</body>
</html>
13.3 待办任务-二次开发题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<div class="main">
<h3>待办任务</h3>
<!-- 新增任务按钮 -->
<a href="javascript:;" onclick="add()" class="icon">+</a>
<ul>
<!-- <li>
<p>xxxxxx</p>
<a class="close" href="javascript:;" onclick="del()">×</a>
</li> -->
</ul>
</div>
<script>
let arr = ['学习javascript', '学习Vue', '学习React']
// 新增功能
function add() {
arr.push(prompt('请输入你的待办任务'))
fn()
}
// 删除功能
function del(index) {
arr.splice(index, 1)
// console.log(index)
// console.log(arr)
fn()
}
// 渲染
function fn() {
let str = ''
for (let i = 0; i < arr.length; i++) {
str += `
<li>
<p>${arr[i]}</p>
<a class="close" href="javascript:;" onclick="del(${i})">×</a>
</li>
`
}
document.querySelector('.main ul').innerHTML = str
}
fn()
</script>
</body>
</html>