1.数组
1.1数组的概念
1.2 数组的创建方式
Js创建数组有两种方式:
- 利用new创建数据
- 利用数组字面量创建数组
1.2.1 利用new 创建数组
var 数组名 = new Array();
var arr = new Array(); // 创建了一个新的空数组,注意Array(),A要大写
1.2.2 利用数组字面量创建数组
var arr = []; // 创建了一个空数组
var arr1 = [1,2,3,'字符串型',true];
1.2.3 数组元素的类型
数组中可以存放任意类型的数据,例如字符串,数字,布尔值等
var arr1 = [1,2,3,'字符串型',true];
总结
数组的作用 | 把多个数据存放在一起 |
---|---|
数组的创建方式 | 1.利用new创建 2.利用数组字面量创建(常用) |
数组元素?数组里面类型有限制吗? | 存放在数组里面的数据称为数组元素;无限制 |
1.3 获取数组元素
1.3.1 数组的索引
索引(下标):用来访问数组元素的序号(数组下标从0开始)
新建.html文件,执行代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 1.数组(Array) : 就是一组数据的集合, 存储在单个变量下的优雅方式
// 2.利用new创建数组
var arr = new Array(); // 创建了一个空数组
// 3.利用数组字面量创建数组 []
var arr = []; // 创建了一个空数组
var arr1 = [1,2,3,'字符串型',true];
// 4.数组里面的数据一定用逗号分隔
// 5. 数组里面的数据 比如1,2 我们称为数组元素
// 6. 获取数组元素 格式 数组名[索引号]
console.log(arr1); // 获取数组arr1里面的全部元素
console.log(arr1[3]); // 获取数组arr1索引为3的元素 字符串型
console.log(arr1[4]); // true
console.log(arr1[5]); // 因为没有这个数组元素 所以输出的结果是 undefined
</script>
</head>
<body>
</body>
</html>
效果如下
1.4 遍历数组
遍历:就是把数组中每个元素从头到尾都访问一遍(类似我们每天早上学生的点名)
新建.html文件,执行代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 遍历数组:就是把数组的元素从头到尾访问一次
var arr = ['red','green','blue'];
for (var i = 0; i < 3; i++) {
console.log(arr[i]);
}
/*
注意:
1.因为我们的数组索引号从0开始,所以i必须从0开始 i < 3
2.输出的时候 arr[i] i 计数器当索引号来用
*/
</script>
</head>
<body>
</body>
</html>
效果如下
1.5 数组的长度
使用"数组名.length"可以访问数组元素的数量(数组长度)。
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 数组长度
var arr = [1,2,3,4,5,6,7,8,9,10];
for (var i =0; i < 10; i++) {
console.log(arr[i]);
}
// 优化版
console.log(arr.length);
console.log('***************');
var arr = [1,2,3,4,5,6,7,8,9,10];
for (var i =0; i < arr.length; i++) {
console.log(arr[i]);
}
// 1.数组的长度是元素个数 不用跟索引号混淆
// 2.arr.length 动态检测数组元素的个数
</script>
</head>
<body>
</body>
</html>
效果如下
总结:
什么是遍历 | 把数组元素从头到尾访问一次 |
---|---|
通过什么来遍历数组里面的元素 | for循环 |
for 里面的i是什么?当什么使用?for里面的数组元素怎么写? | i是计数器,当索引号使用,arr[i]是数组元素 第i个数组元素 |
如何获取数组的长度 | arr.length |
数组索引号和数组长度有什么关系? | 索引号从0开始,数组长度是元素个数 |
1.5.1案例:数组求和及平均值
求数组[2,6,1,7,4] 里面所有元素的和以及平均值。
新建.html文件,执行代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
/*
案例分析
1.声明一个求和变量 sum
2.遍历这个数组,把里面每个数组元素加到sum里面
3.用求和变量sum除以数组的长度就可以得到数组的平均值
*/
var arr = [2,6,1,7,4];
var sum = 0;
var average = 0;
for (var i = 0; i < arr.length; i++) {
sum += arr[i] // 此处加的是数组元素arr[i],不是计数器i
}
average = sum / arr.length;
console.log('所有元素的和:'+sum);
console.log('平均值为:'+ average);
// 想要输出多个变量,用逗号分隔即可
console.log(sum,average);
</script>
</head>
<body>
</body>
</html>
效果如下
1.5.2 案例:数组最大值
求数组[2,6,1,77,52,25,7]中的最大值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
/*
案例分析:
1.声明一个保存最大元素的变量max
2.默认最大值可以取数组中的第一个元素
3.遍历这个数组,把里面每个数组元素和max相比较。
4.如果这个数组元素大于max就把这个数组元素存到max里面,否则继续下一轮比较。
5.最后输出这个max
*/
var arr = [2,6,1,77,52,25,7];
var max = arr[0];
for (var i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
console.log('该数组的最大值为:'+ max);
// 同理,拓展求最小值
var min = arr[0];
for (var i =1; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i];
}
}
console.log('该数组的最小值为:'+ min);
</script>
</head>
<body>
</body>
</html>
效果如下:
1.5.3 案例:数组转换为分割字符串
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
var arr = ['red','green','blue','pink'];
var str = '';
var sep = '|';
for ( var i = 0; i < arr.length;i++) {
str += arr[i] + sep;
}
console.log(str);
</script>
</head>
<body>
</body>
</html>
效果如下
1.6 数组中新增元素
可以通过修改length长度以及索引号增加数组元素
1.6.1 通过修改length长度新增数组元素
1.6.2 通过修改数组索引新增数组元素
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 1. 新增数组元素 修改length长度
var arr = ['red','green','blue'];
console.log(arr.length);
arr.length = 5; // 把我们数组的长度修改为了5,里面应该有五个元素
console.log(arr); // (5) ['red', 'green', 'blue', empty × 2]
console.log(arr[3]); // undefined
console.log(arr[4]); // undefined
arr.length = 2;
console.log(arr); // (2) ['red', 'green']
arr.length = 3; // (3) ['red', 'green', empty]
console.log(arr);
// 新增数组元素 修改索引号
var arr1 = ['red','green','blue'];
arr1[3] = 'yellow';
console.log(arr1); // (4) ['red', 'green', 'blue', 'yellow']
arr1[4] = 'orange';
console.log(arr1); // (5) ['red', 'green', 'blue', 'yellow', 'orange']
// 如果位置被占用,替换原来的数组元素
arr1[2] = 'blank';
console.log(arr1); // (5) ['red', 'green', 'blank', 'yellow', 'orange']
// 特别注意: 不要给数组名直接赋值,否则会覆盖掉以前的数据
arr1 = '你好'
console.log(arr1);
</script>
</head>
<body>
</body>
</html>
效果如下
1.6.3 案例 :数组新增元素
新建一个数组,里面存放100个整数(1~100)
案例分析:
1.使用循环来追加数组
2.声明一个空数组arr
3.循环中的计数器i可以作为数组元素存入
4.由于数组的索引号是从0开始的,因此计数器从0开始更合适,存入的数组元素要+1
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
var arr = [];
for (var i = 0;i < 100; i++) {
// arr = i; 不要直接给数组名赋值 否则以前的元素都没了
arr[i] = i + 1;
}
console.log(arr);
</script>
</head>
<body>
</body>
</html>
效果如下
1.6.4 案例:筛选数组
要求:将数组[2,0,6,1,77,0,52,0,25,7]中大于等于10的元素选出来,放入新数组。
案例分析
1.声明一个新数组用于存放新数据newArr
2.遍历原来的旧数组,找出大于等于10的元素
3.依次追加给新数组newArr
新建.html文件,执行代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 方法一
/* var arr = [2,0,6,1,77,0,52,0,25,7];
var newArr = [];
var j = 0;
for (var i = 0;i < arr.length; i++) {
if (arr[i] >= 10) {
// 新数组索引号应该从0开始 依次递增
newArr[j] = arr[i]
j++;
}
}
console.log(newArr); */
// 方法二
var arr = [2,0,6,1,77,0,52,0,25,7];
var newArr = []; // 刚开始 newArr.length 就是0
console.log(newArr.length); // 0
for (var i = 0;i < arr.length; i++) {
if (arr[i] >= 10) {
// 新数组索引号应该从0开始 依次递增
newArr[newArr.length] = arr[i]
}
}
console.log(newArr);
</script>
</head>
<body>
</body>
</html>
效果如下:
1.7 数组案例
1.7.1 案例:删除指定数组元素(数组去重)
要求:将数组[2,0,6,1,77,0,52,0,25,7]的0去掉后,形成一个不包含0的新数组。
案例分析
1.需要一个新数组用于存放筛选之后的数据
2.遍历原来的数组,把不是0的数据添加到新数组里面(此时要注意采用数组名+索引的格式接收数据)。
3.新数组里面的个数,用length不断累加
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
var arr = [2,0,6,1,77,0,52,0,25,7];
var newArr = [];
for (var i = 0; i < arr.length;i++) {
if (arr[i] != 0) {
newArr[newArr.length] = arr[i];
}
}
console.log(newArr);
</script>
</head>
<body>
</body>
</html>
效果如下
1.7.2 案例:翻转数组
要求:将数组[‘red’,‘green’,‘blue’,‘pink’,‘purple’]的内容反过来存放。
输出: [‘purple’,‘pink’,‘blue’,‘green’,‘red’]
分析
案例分析
1.声明一个新数组newArr
2.把旧数组索引号第4个取过来(arr.length - 1) ,给新数组索引号第0 个元素(newArr.length)
3.采用递减的方式 i–
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
var arr = ['red','green','blue','pink','purple'];
var newArr = [];
for (var i = arr.length -1; i >= 0;i--) {
newArr[newArr.length] = arr[i];
}
console.log(newArr);
</script>
</head>
<body>
</body>
</html>
效果如下
1.7.3 案例: 数组排序(冒泡排序)
冒泡排序:是一种算法,把一系列的数据按照一定的顺序进行排列显示(从小到大或者从大到小)。
例如:我们可以将数组[5,4,3,2,1]中的元素按照从小到大的顺序排序,输出:1 ,2 ,3 ,4 ,5 。反之亦可。
冒泡排序是一种简单的排序算法。它重复走访过要排序的数列 ,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。
回顾之前交换变量代码,如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 交换两个变量
var num1 = '1号位';
var num2 = '2号位';
var temp;
temp = num1;
num1 = num2;
num2 = temp;
console.log(num1,num2);
</script>
</head>
<body>
</body>
</html>
分析原理:
新建.html文件,执行文件如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 冒泡排序
// var arr = [4,1,2,3,5]
var arr = [5,4,3,2,1]
for (var i = 0; i <= arr.length - 1;i++) { // 外层循环管趟数
for (var j = 0; j <= arr.length -i - 1;j++) { // 里层循环管每一趟的交换次数
// 内部交换两个变量的值 前一个和后一个数组元素相比较
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j+1] = temp;
}
}
}
console.log(arr);
</script>
</head>
<body>
</body>
</html>
效果如下
2. 函数
2.1 函数的概念
在JS里面,可能会定义非常多的相同代码或者功能相似的代码,这些代码可能需要大量重复使用。
虽然for循环语句也能实现一些简单的重复操作,但是比较具有局限性,此时我们就可以使用JS中的函数。
函数:就是封装了一段可被重复调用执行的代码块。通过此代码可以实现大量代码的重复使用。
新建.html文件,执行代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 1.求1~100的累加和
var sum = 0;
for (var i = 1; i <= 100; i++) {
sum += i;
}
console.log(sum); // 5050
// 2. 求1~50的累加和
var sum = 0;
for (var i = 1; i <= 50;i++) {
sum += i
}
console.log(sum); // 1275
// 3. 函数的方法做上面的计算
// 函数就是封装了一段可以被重复执行调用的代码块,目的:让大量代码重复使用
function getSum(num1,num2) {
var sum = 0;
for (var i = num1;i <= num2;i++) {
sum += i
}
console.log(sum);
}
getSum(1,100) // 5050
getSum(1,50) // 1275
</script>
</head>
<body>
</body>
</html>
效果如下:
2.2 函数的使用
函数在使用时分为两步:声明函数和调用函数。
新建.html文件,执行如下代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 函数使用分为两步:声明函数和调用函数
// 1.声明函数
function 函数名() {
// 函数体
}
/*
注意:
(1) function 是声明函数的关键字,全部小写
(2) 函数是做某件事情,函数名一般是动词 例如:sayHello
(3) 函数不调用自己不执行
*/
// 2.调用函数
// 函数名();
function sayHello() {
console.log('今天你好吗?');
}
sayHello();
// 调用函数的时候千万不要忘记加小括号
</script>
</head>
<body>
</body>
</html>
效果如下
2.2.1 函数的封装
函数的封装是把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口。
简单理解:封装类似于将电脑配件整合组装到机箱中(类似于快递打包)
2.2.2 函数封装案例:计算1~100之间的累加和
新建.html文件,执行代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 利用函数计算1~100之间的累加和
// 1.声明函数
function getSum(num1,num2) {
var sum = 0;
for (var i = num1; i <= num2;i++) {
sum += i;
}
console.log(sum);
}
// 2.调用函数
getSum(1,100); // 5050
// 计算55~100之间的累加和
getSum(55,100) // 3565
</script>
</head>
<body>
</body>
</html>
效果如下
小结
函数的作用 | 大量代码重复使用(封装了一段可以被重复执行的代码块) |
---|---|
声明函数的关键字 | function |
如何调用函数 | 函数名(); |
封装什么意思 | 打包 |
2.3 函数的参数
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 1.函数可以重复相同的代码
function cook() {
console.log('酸辣土豆丝');
}
cook(); // 酸辣土豆丝
cook(); // 酸辣土豆丝
// 2.可以利用函数实现函数重复不同的代码
/*
function 函数名(形参1,形参2...) {
函数体
}
函数名(实参1,实参2...);
形参:在声明函数的小括号里面是 形参 (形式上的参数)
实参:在函数调用的小括号里面是实参 (实际的参数)
parameter 形参 argument 实参
*/
// 3.形参和实参的执行过程
function cook_one(para) { // 形参是接收实参的,相当于一个变量 para = '鱼香肉丝'
console.log(para);
}
cook_one('鱼香肉丝') // 鱼香肉丝
cook_one('韭菜鸡蛋') // 韭菜鸡蛋
// 4.函数的参数可以有,也可以没有个数不限
</script>
</head>
<body>
</body>
</html>
效果如下
2.3.1 案例演示
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 1.利用函数求任意两个数的和
function numSum(num1,num2) {
var sum = 0;
sum = num1 + num2;
console.log(sum);
}
// 2.求1和8的和
numSum(1,8); // 9
// 2.利用函数求任意两个数之间的和
function getSum(num1,num2) {
var totle = 0
for (var i = num1; i <= num2; i++) {
totle += i;
}
console.log(totle);
}
// 求1和8之间的和
getSum(1,8) // 36
/*
3. 注意点:
(1) 多个参数之间用逗号隔开
(2) 形参可以看做是不用声明的变量
*/
</script>
</head>
<body>
</body>
</html>
效果如下
2.3.2 函数形参和实参个数不匹配问题
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 函数形参实参个数匹配
function getSum(num1,num2) {
console.log(num1 + num2);
}
// 1.如果实参的个数和形参的个数一致,则正常输出结果
getSum(1,2); // 3
// 2.如果实参的个数多于形参的个数,会取到形参的个数
getSum(1,2,3,4) // 3
getSum(1,8,9) // 9
// 3.如果实参的个数小于形参的个数,多于的形参定义为undefined 最终的结果就是NaN
getSum(1) // NaN
getSum() // NaN
// 建议:我们尽量让实参的个数和形参相匹配
</script>
</head>
<body>
</body>
</html>
效果如下
小结
2.4 函数的返回值
2.4.1 return语句
有时候,我们会希望函数将返回值返回给调用者,此时通过return语句既可以实现。
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 1.函数是做某件事或者实现某种功能
function cook(aru) {
console.log(aru);
}
console.log('鱼香肉丝'); // 鱼香肉丝
// 2.函数的返回值格式
/*
function 函数名() {
return 需要返回的结果;
}
函数名();
注意点:
(1) 函数只是实现某种功能,最终的结果需要返回给函数的调用者函数名(), 通过return 实现的
(2) 只是函数遇到return 就把后面的结果 返回给函数的调用者 函数名() = return后面的结果
*/
// 3.代码验证
function getResult() {
return '哈喽,你好吗';
}
getResult(); // 相当于做了 getResult() = '哈喽,你好吗'
console.log(getResult()); // 哈喽,你好吗
// 完善最前面代码
function cookOne(aru) {
return aru;
}
console.log(cookOne('水煮肉片')); // 水煮肉片
// 优化代码:求两个数的和
function getSum(num1,num2) {
return num1 + num2;
}
console.log(getSum(5,19)); // 24
</script>
</head>
<body>
</body>
</html>
效果如下
2.4.2 案例:利用函数求任意两个数的最大值
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 利用函数,求两个数的最大值
function getMax(num1,num2) {
if (num1 > num2) {
return num1;
} else {
return num2;
}
}
// 反之求最小值
function getMin(num1,num2) {
if (num1 > num2) {
return num2;
} else {
return num1;
}
}
// 求28和35的最大值,最小值
getMax(28,35);
console.log( getMax(28,35)); // 35
getMin(28,35);
console.log(getMin(28,35)); // 28
// 用三元表达式进行优化
function getMax1(num1,num2) {
return num1 > num2 ? num1 : num2;
}
function getMin1(num1,num2) {
return num1 > num2 ? num2 : num1;
}
console.log( getMax1(18,69)); // 69
console.log( getMin1(32,41)); // 32
</script>
</head>
<body>
</body>
</html>
效果如下
2.4.3 案例:利用函数求任意一个数组中的最大值
利用函数求数组[5,2,99,101,67,77]中的最大数值
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 利用函数求数组 [5,2,99,101,67,77]中的最大数值
function getArrMax(arr) { // arr 接收一个数值
var max = arr[0];
for (var i = 1; i <= arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
// getArrMax([5,2,99,101,67,77]) // 实参是一个数组送过去
// 在实际开发里面,我们经常用一个变量来接收 函数的返回结果,使用更简单
var re = getArrMax([5,2,99,101,67,77]);
console.log(re); // 101
// 任意一个数组也可以求最值
var msg = getArrMax([3,6,12,6,88,199,5,2])
console.log(msg); // 199
</script>
</head>
<body>
</body>
</html>
效果如下
2.4.4 return 终止函数
return语句之后的代码不被执行
2.4.5 return 的返回值
return 只能返回一个值。如果用逗号隔开多个值,以最后一个为准。(返回多个值的话可以用数组方式来实现)
2.4.6 函数没有 return 返回undefined
函数都是有返回值的
1.如果有return 则返回return后面的值
2.如果没有return 则返回undefined
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 函数返回值注意事项
// 1. return 终止函数
function getSum(num1,num2) {
return num1 + num2; // return 后面的代码不会被执行
alert('我是不会被执行的');
}
console.log(getSum(1,2));
// 2. return 只能返回一个值
function fn(num1,num2) {
return num1,num2; // 返回的结果是最后一个值
}
console.log(fn(1,2));
// 3.我们求任意两个数的加减乘除的结果
function getResult(num1,num2) {
return [num1 + num2, num1 - num2, num1 * num2, num1 / num2];
}
var re = getResult(8,4); // 返回的是一个数组
console.log(re); // [12, 4, 32, 2]
// 4.我们的函数如果有return 则返回的是return 后面的值,如果函数没有return 则返回undefined
function fun1() {
return 666;
}
console.log(fun1()); // 返回 666
function fun2() {
}
console.log(fun2()); // 返回 undefined
</script>
</head>
<body>
</body>
</html>
效果如下
2.4.7 break,continue,return的区别
break | 结束当前的循环体(如for、while) |
---|---|
continue | 跳出本次循环,继续执行下次循环(如for、while) |
return | 不仅可以退出循环,还能够返回return语句中的值,同时还可以结束当前的函数体内的代码 |
2.5 通过榨汁机看透函数
2.5.1 小结案例
新建.html文件,执行代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 1.写一个函数,用户输入任意两个数字的任意算术运算(简单的计算器小功能),并能弹出运算后的结果
function getResult1(operator,num1,num2) {
var operator = prompt("请输入您的运算符('+','-','*','/')");
var num1 = prompt('请输入您的第一个数字');
var num2 = prompt('请输入您的第二个数字');
if (operator == '+') {
return parseFloat(num1) + parseFloat(num2)
} else if (operator == '-') {
return num1 - num2
} else if (operator == '*') {
return num1 * num2
} else if (operator == '/') {
return num1 / num2
} else {
return '运算符错误';
}
}
alert(getResult1());
// 2.写一个函数,用户输入任意两个数字的最大值,并能出弹运算后的结果
function getMax(num1,num2) {
var num1 = parseInt(prompt('请输入数字'));
var num2 = parseInt(prompt('请输入数字'));
return num1 > num2 ? num1 : num2;
}
alert(getMax())
// 3. 写一个函数,用户输入任意三个不同数字的最大值,并能弹出运算后的结果
var num1 = parseInt(prompt('输入第一个数字'));
var num2 = parseInt(prompt('输入第二个数字'));
var num3 = parseInt(prompt('输入第三个数字'));
var arr = [num1,num2,num3]
var max = num1;
function getMaxValue(num1,num2,num3) {
for (var i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
alert(getMaxValue())
// 4.写一个函数,用户输入一个数判断是否是素数,并返弹出回值(又叫质数,只能被1和自身整除的数)
function judgePrime(num1) {
var num1 = parseFloat(prompt('请输入数字'));
for (var i= 2; i < num1;i++) {
if (num1 % i == 0) {
return num1 + '不是质数';
}
}
return num1 + '是质数';
}
alert(judgePrime())
</script>
</head>
<body>
</body>
</html>
2.6 arguments的使用
当我们不确定有多少个参数传递的时候,可以用arguments来获取。在JavaScript中,arguments实际上它是当前函数的一个内置对象。所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有实参。
arguments展示形式是一个伪数组,因此可以进行遍历。伪数组具有以下特点:
1.具有length属性
2.安索引方式储存数据
3.不具有数组的push,pop等方式
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// arguments 的使用
// 只有函数才有arguments对象,而且是每个函数都内置好了这个arguments
function fn() {
console.log(arguments); // 里面存储了所有传递过来的实参
console.log(arguments.length); // 3
console.log(arguments[2]); // 3
// 可以按照数组的方式遍历arguments
for (var i = 0; i < arguments.length;i++) {
console.log(arguments[i]);
}
}
fn(1,2,3);
fn(1,2,3,4,5,6,7)
/*
注意:
1. 伪数组 并不是真正意义上的数组
2. 按照索引的方式进行存储的
3. 它没有真正数组的一些方式 pop() push() 等等
*/
</script>
</head>
<body>
</body>
</html>
效果如下
2.6.1 案例:利用函数求任意个数的最大值
新建.html文件,执行代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 利用函数求任意个数的最大值
function getMax() { // 相当于 arguments = [1,2,3]
var max = arguments[0];
for (var i = 1; i < arguments.length;i++) {
if (arguments[i] > max) {
max = arguments[i];
}
}
return max;
}
console.log(getMax(1,2,3));
console.log(getMax(12,43,546,7575,435,3));
console.log(getMax(12,65,76,23,7,2,34));
console.log(getMax(4,5,7,4,2,6,1));
</script>
</head>
<body>
</body>
</html>
效果如下:
2.7 函数案例
2.7.1 案例:利用函数封装方式,翻转任意一个数组
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 利用函数翻转任意数组 reverse 翻转
function reverse(arr) {
var newArr = [];
for (var i = arr.length - 1; i >= 0;i--) {
newArr[newArr.length] = arr[i];
}
return newArr;
}
var arr1 = reverse([1,3,5,7,9,11]);
console.log(arr1); // [11, 9, 7, 5, 3, 1]
var arr2 = reverse(['red','pink','blue']);
console.log(arr2); // ['blue', 'pink', 'red']
</script>
</head>
<body>
</body>
</html>
效果如下
2.7.3 案例:利用函数封装的方式,对数组排序—冒泡排序
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 利用函数冒泡排序
function sort(arr) {
for (var i = 0; i < arr.length - 1; i++) {
for (var j =0; j < arr.length -i -1;j++) {
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] =arr[j+1];
arr[j+1] = temp;
}
}
}
return arr;
}
var arr1 = sort([1,4,3,2,9]);
console.log(arr1); // [1, 2, 3, 4, 9]
var arr2 = sort([1,44,68,23,5,99,3]);
console.log(arr2); // [1, 3, 5, 23, 44, 68, 99]
</script>
</head>
<body>
</body>
</html>
Python的冒泡写法
def sort(items):
for i in range(len(items) - 1):
for j in range(len(items) - 1 - i):
if items[j] > items[j + 1]:
items[j], items[j + 1] = items[j + 1], items[j]
return items
效果如下
2.7.4 案例:利用函数判断闰年
要求:输入一个年份,判断是否是闰年(闰年:能被4整除并且不能被100整除,或者能被400整除)
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 利用函数判断闰年
function isRunYear(year) {
// 如果是闰年,返回true,否则,返回false
var flag = false;
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
flag = true;
}
return flag;
}
console.log(isRunYear(2000)); // true
console.log(isRunYear(2014)); // false
</script>
</head>
<body>
</body>
</html>
效果如下
2.7.5 案例:函数可以调用另外一个函数
因为每个函数都是独立的代码块,用于完成特殊任务,因此经常会用到函数相互调用的情况。
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 函数是可以相互调用的
function fn1() {
console.log(1111);
fn2(); // 在fn1函数里面调用了fn2函数
console.log('fn1');
}
fn1();
function fn2() {
console.log(2222);
console.log('fn2');
}
</script>
</head>
<body>
</body>
</html>
效果如下
2.7.6 案例:用户输入年份,输出当前年2月份的天数
要点:如果是闰年,则2月份是29天,如果是平年,则2月份是28天
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 用户输入年份,输出当前年份2月份的天数
function backDay() {
var year = prompt('请你输入年份:');
if(isRunYear(year)) { // 调用函数需要加小括号
alert('当前年份是闰年,2月份有29天');
} else {
alert('当前年份是平年,2月份有28天')
}
}
backDay();
// 利用函数判断闰年
function isRunYear(year) {
// 如果是闰年,返回true,否则,返回false
var flag = false;
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
flag = true;
}
return flag;
}
</script>
</head>
<body>
</body>
</html>
效果如下
2.8 函数的两种声明方式
新建.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 函数的2种声明方式
// 1.利用函数关键字自定义函数(命名方式)
function fn() {
console.log('fn');
}
// 调用方式
fn();
// 2. 函数表达式(匿名函数)
// 方式: var 变量名 = function() {};
var fun = function() {
console.log('我是函数表达式');
}
fun();
/*
注意:
1.fun是变量名,不是函数名
2.函数表达式声明方式跟变量差不多,只不过变量里面存的是值,而函数表达式里面存的是函数
3.函数表达式也可以进行传递参数
*/
var color = function(arg) {
console.log('你需要的颜色');
console.log(arg);
}
color('red') // 你需要的颜色 红色
</script>
</head>
<body>
</body>
</html>
效果如下:
3.作用域
3.1 作用域的概述
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字的冲突。
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
/*
1.javaScript作用域:就是代码名字(变量)在某个范围内起作用和效果 目的是为了提高程序的可靠性更重要的是减少命名冲突
2.js的作用域(es6版本)之前:全局作用域 局部作用域
3.全局作用域:整个script标签 或者是一个单独的js文件
4.局部作用域(函数作用域):在函数内部就是局部作用域,这个代码的名字只在函数内部起效果和作用
5.全局作用域和局部作用域的相同变量不会发生冲突,同一个作用域下变量一样会冲突
*/
// 全局作用域
var num = 10;
console.log(num);
function fn() {
// 局部作用域
var num = 20;
console.log(num);
}
fn();
</script>
</head>
<body>
</body>
</html>
效果如下
3.2 变量作用域的分类
在JavaScript中,根据作用域不同,变量可以分为两种:
全局变量
局部变量
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 变量作用域:根据作用域的不同,变量分为全局变量和局部变量
// 1.全局变量:
// (1) 在全局作用域下的变量 在全局下都可以使用
// (2) 在函数的内部 没有声明直接赋值的变量(重点注意)
var num = 10; // num就是一个全局变量
console.log(num); // 10
function fn() {
console.log(num);
}
fn(); // 10
// 2. 局部变量
// (1) 在局部作用域下的变量 在函数内部的变量就是局部变量
// (2) 函数的形参也可以看作是局部变量(重点注意)
function fun() {
var num1 = 10; // num1就是局部变量,只能在函数内部使用
name = '张三'; // 这是全部变量,不建议使用
}
fun();
console.log(name); // '张三'
console.log(num1); // Uncaught ReferenceError: num1 is not defined
// function fun1(arr) {
// var num1 = 10; // num1就是局部变量,只能在函数内部使用
// name = '张三'; // 这是全部变量
// }
// fun1();
// console.log(arr); // Uncaught ReferenceError: arr is not defined
/*
3.从执行效率来看全局变量和局部变量
(1) 全局变量只有浏览器关闭的时候才会销毁,比较占内存
(2) 局部变量 当我们程序执行完毕就会销毁,比较节约内存资源
*/
</script>
</head>
<body>
</body>
</html>
效果如下:
3.3 JavaScript没有块级作用域
ECMAScript 6(简称ES6)是于2015年6月正式发布的JavaScript语言的标准,正式名为ECMAScript 2015(ES2015)。它的目标是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言 。
另外,一些情况下ES6也泛指ES2015及之后的新增特性,虽然之后的版本应当称为ES7、ES8等。
新建.html文件,代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// js中没有块级作用域 js的作用域:全局作用域 局部作用域 现阶段我们js中没有块级作用域
// js中的块级作用域在es6版本之后新增的块级作用域
// 块级作用域 {}
if (3 < 5) {
var num = 10;
}
console.log(num); // 10
</script>
</head>
<body>
</body>
</html>
效果如下
3.3 作用域链
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 作用域链:内部函数访问外部函数的变量,采用的是链式查找的方法来决定取哪个值,这种结构我们称为作用域链
// 也就是从内到外,一级一级的查找,就近原则
var num = 10;
var year = 2022;
function fn() { // 外部函数
var num = 20;
function fun() { // 内部函数
console.log(num); // 20
console.log(year); // 2022
}
fun();
}
fn();
</script>
</head>
<body>
</body>
</html>
效果如下
3.3.1 案例:结果是几?
新建.html文件,执行代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 案例1:结果是几?
function f1() {
var num = 123;
function f2() {
console.log(num);
}
f2();
}
var num = 456;
f1(); // 123
// 案例2:结果是几?
var a = 1;
function fn1() {
var a = 2;
var b = '22';
fn2();
function fn2() {
var a = 3;
fn3();
function fn3() {
var a = 4;
console.log(a); // 4
console.log(b); // '22'
}
}
}
fn1();
</script>
</head>
<body>
</body>
</html>
效果如下
4.JavaScript预解析
JavaScript代码是由浏览器中的JavaScript解析器来执行的。JavaScript解析器在运行JavaScript代码的时候分为两步:预解析和代码执行。
问题背景:
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 问题1:执行结果是什么?
// console.log(num1); 报错 Uncaught ReferenceError: num1 is not defined
// 问题2:执行结果是什么?
console.log(num2); undefined
var num2 = 10;
// 问题3:执行结果什么?
function fn() {
console.log('放下面可以调用');
}
fn();
fn1();
function fn1() {
console.log('放上面可以调用');
}
// 问题4:执行结果是什么?
var fun = function() {
console.log('放下面可以调用');
}
fun();
fun1(); // 38-预解析.html:28 Uncaught TypeError: fun1 is not a function
var fun1 = function() {
console.log('放上面可以调用吗');
}
</script>
</head>
<body>
</body>
</html>
效果如下
基础背景回顾:
上面问题1的报错和问题4的报错是什么原因呢?
新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 问题1:执行结果是什么?
// console.log(num1); 报错 Uncaught ReferenceError: num1 is not defined
// 问题2:执行结果是什么?
console.log(num2); undefined (此处用变量提升解释)
var num2 = 10;
// 第12,13行代码相当于执行了以下代码
// var num2;
// console.log(num2); 此时只声明没赋值
// num2 = 10;
// 问题3:执行结果什么?
function fn() {
console.log('放下面可以调用');
}
fn();
fn1();
function fn1() {
console.log('放上面可以调用');
}
/*
函数提升
不管调用的时候写上面还是下面,在预解析的时候都会提上面
*/
// 问题4:执行结果是什么?
var fun = function() {
console.log('放下面可以调用');
}
fun();
fun1(); // 38-预解析.html:28 Uncaught TypeError: fun1 is not a function
var fun1 = function() {
console.log('放上面可以调用吗');
}
// 第36行,37行,38行,38行代码相当于执行了以下代码
// var fun1;
// fun1(); 此时只声明没给函数
// var fun1 = function() {
// console.log('放上面可以调用吗');
// }
/* 如果调整为:
var fun1 = function() {
console.log('放上面可以调用吗');
}
fun1();
就可以正常运行 */
/*
知识点:
1. JS引擎运行js分为两步:预解析 代码执行
(1) 预解析 js引擎会把js里面所有的var 还有 function提升到当前作用域的最前面
(2) 代码执行 按照代码书写的顺序从上往下执行
2.预解析分为变量预解析(变量提升)和 函数预解析 (函数提升)
(1) 变量提升 就是把所有的变量声明提升到当前的作用域最前面 不提升赋值操作 (问题2,问题4)
(2) 函数提升 就是把所有的函数声明提升到当前作用域的最前面 不调用函数 (问题3)
总结:
1.函数表达式调用时,必须写在函数表达式的下面
2.变量初始化放在打印变量之前
*/
</script>
</head>
<body>
</body>
</html>
4.1 预解析案例:结果是几?
案例一,新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 案例1
var num = 10;
fun();
function fun() {
console.log(num);
var num = 20;
}
/* // 相当于执行了以下操作
// 1.变量提升
var num;
// 2.函数提升
function fun() {
console.log(num);
var num = 20; // 函数里面的也需要变量提升
}
// 3.剩下的依次写
num = 10;
fun();
// 4.对函数里面的进行变量提升,这样就成了
var num;
function fun() {
var num;
console.log();
num = 20;
}
num = 10;
fun(); */
// 按照作用域链一级一级执行,所以 本案例执行结果为undefined;
</script>
</head>
<body>
</body>
</html>
效果如下
案例二,新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
var num = 10;
function fn() {
console.log(num);
var num = 20;
console.log(num);
}
fn();
// 相当于执行了以下代码
// var num;
// function fn() {
// var num;
// console.log(num);
// num = 20;
// console.log(num);
// }
// num = 10;
// fn();
// 所以,根据作用域链的就近原则,结果为: undefined 20
</script>
</head>
<body>
</body>
</html>
效果如下
案例三,新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
var a = 18;
f1();
function f1() {
var b = 9;
console.log(a);
console.log(b);
var a = '123';
}
// 上面代码相当于执行了下面代码
// var a;
// function f1() {
// var b;
// var a;
// b = 9;
// console.log(a);
// console.log(b);
// a = '123';
// }
// a = 18;
// f1();
// 所以 根据作用域链来分析,该段代码返回值为: undefined 9
</script>
</head>
<body>
</body>
</html>
效果如下
案例四,新建.html文件,执行代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
f1();
console.log(c);
console.log(b);
console.log(a);
function f1() {
var a = b = c = 9; // 相当于 var a = 9;b =9; c = 9;
console.log(a);
console.log(b);
console.log(c);
}
// 以上代码相当于执行了下面代码
// function f1() {
// var a;
// a = 9;
// b = 9; // b和c没有直接赋值 没有var声明,当全局变量看,a在函数里面有var,当局部变量看
// c = 9;
// console.log(a);
// console.log(b);
// console.log(c);
// }
// f1();
// console.log(c);
// console.log(b);
// console.log(a);
// 根据作用域的就近原则,其值为 9,9,9,9,9,报错
</script>
</head>
<body>
</body>
</html>
效果如下