一、初识JavaScript
1. JavaScript概述
- Java是世界上最流行的语言之一,是一种运行在客户端的脚本语言(Script是脚本的意思)
- 脚本语言:不需要编译,运行过程中由js解释器(js引擎)逐行来进行解释并执行
- 现在也可以基于Node.js技术进行服务器编程
2. JavaScript的作用
- 表单动态校验(密码强度检测)(JS产生最初的目的)
- 网页特效
- 服务端开发(Node.js)
- 桌面程序(Electron)
- App(Cordova)
- 控制硬件-物联网(Ruff)
- 游戏开发(cocos2d-js)
3. HTML/CSS/JS的关系
1)HTML/CSS标记语言:描述类语言
- HTML决定网页结构和内容(决定看到什么),相当于人的身体
- CSS决定网页呈现给用户的模样(决定好不好看),相当于给人穿衣服、化妆
2)JS脚本语言:编程类语言
- 实现业务逻辑和页面控制(决定功能),相当于人的各种动作
3)编程语言和标记语言的区别
- 编程语言有很强的逻辑和行为能力,在编程语言里,你会看到很多if else、for、while等具有逻辑性和行为能力的指令,这是主动的。
- 标记语言(html)不用于向计算机发出指令,常用于格式化和链接,标记语言的存在是用来被读取的,它是被动的。
4. 浏览器执行JS简介
浏览器分为两部分:渲染引擎和JS引擎
- 渲染引擎:用来解析HTML与CSS,俗称内核,比如chrome浏览器的blink,老版本的webkit
- JS引擎:也称为JS解释器,用来读取网页中的Javascript代码,并对其处理后运行,比如chrome浏览器的V8
浏览器本身并不会执行JS代码,JS引擎执行代码时逐行解释每一句源码(转换为机器语言),然后由计算机去执行,所以JavaScript语言归为脚本语言,会逐行解释执行。
5. JS的组成

6、JS的3种书写方式:
7、JS的注释
建议:单行用"//",多行用“/*”
8、JS的输入输出语句
二、变量
1、变量概述
-
变量是用来存放数据的容器
-
通俗来说变量就是一个装东西的盒子
-
我们可以通过变量名获取数据,甚至修改数据
-
本质:变量是程序中在内存中申请的一块用来存放数据的空间,类似于酒店的房间,一个房间就可以看做是一个变量

2、变量使用
使用步骤:
1)声明变量
//声明变量
var age;
2)赋值
//赋值,把值存入变量中
age = 18;
3)变量的初始化
- 变量的初始化:声明一个变量并赋值
//声明变量同时赋值
var age = 18;
4)变量语法扩展
1. 更新变量
一个变量被重新赋值后,它原有的值就会被覆盖,变量值将以最后一次赋的值为准。
var age = 18;
age = 66;//最后的结果就是66,因为18被覆盖了
2. 声明多个变量
var age = 18;
username = 'Mickey';
score = '66';
3. 声明变量特殊情况
- 只声明,不赋值:undefined
- 不声明,不赋值,直接使用:报错
- 不声明,只赋值:可以正常使用,但是不建议使用,变成了全局变量
5)变量命名规范
- 由字母、数字、下划线、美元符号组成
- 严格区分大小写
- 不能以数字开头
- 不能是关键字、保留字
- 变量名必须见名知意
- 遵守驼峰命名法,首字母小写,后面的单词首字母需要大写
案例:交换两个变量的值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>交换两个变量的值</title>
</head>
<body>
<script>
var apple1 = '青苹果';
var apple2 = '红苹果';
var temp = '';
temp = apple1;
apple1 = apple2;
apple2 = temp;
alert(apple1 + apple2 + temp);
</script>
</body>
</html>
结果如图:
三、数据类型
1. 数据类型简介
-
1)为什么需要数据类型
在计算机中,不同的数据所需占用的存储空间是不同的,为了便于把数据分成所需内存大小不同的数据,充分利用存储空间,于是定义了不同的数据类型。 -
2)变量的数据类型
变量是用来存储值的所在处,它们有名字和数据类型。变量的数据类型决定了如何将代表这些值的位存储到计算机的内存中。
JavaScript 是一种弱类型或者说动态语言。这意味着不用提前声明变量的类型,在程序运行过程中,类型会被自动确定:
var age = 10; // 这是一个数字型
var areYouOk = '是的'; // 这是一个字符串
在代码运行时,变量的数据类型是由JS引擎 根据 = 右边变量值的数据类型来判断的,运行完毕之后, 变量就确定了数据类型。JavaScript 拥有动态类型,同时也意味着相同的变量可用作不同的类型:
var x = 6; // x 为数字
var x = "Bill"; // x 为字符串
JS 把数据类型分为两类:
- 简单数据类型 (Number,String,Boolean,Undefined,Null)
- 复杂数据类型 (object)
2. 简单数据类型(基本数据类型)

1) 数字型进制
最常见的进制有二进制、八进制、十进制、十六进制。
在JS中八进制前面加0,十六进制前面加 0x
2) 数字型范围
JavaScript中数值的最大和最小值
- 最大值:Number.MAX_VALUE,这个值为: 1.7976931348623157e+308
- 最小值:Number.MIN_VALUE,这个值为:5e-32
3) 数字型三个特殊值
- infinity:代表无穷大,大于任何数值
- -infinity:代表无穷小,小于任何数值
- NaN:Not a Number,代表一个非数值
4) isNaN
用来判断一个变量是否为非数字的类型,返回 true 或者 false

1)字符串引号嵌套
JS 可以用单引号嵌套双引号 ,或者用双引号嵌套单引号 (外双内单,外单内双)
2)字符串转义符
类似HTML里面的特殊字符,字符串中也有特殊字符,我们称之为转义符。
转义符都是 \ 开头的,常用的转义符及其说明如下:

3)字符串拼接(数值相加 ,字符相连)
- 多个字符串之间可以使用 + 进行拼接,其拼接方式为 字符串 + 任何类型 = 拼接之后的新字符串
- 拼接前会把与字符串相加的任何类型转成字符串,再拼接成一个新的字符串
-
2.3 布尔型Boolean
布尔类型有两个值:true 和 false ,其中 true 表示真(对),而 false 表示假(错)。
布尔型和数字型相加的时候, true 的值为 1 ,false 的值为 0。 -
2.4 Undefined和 Null
Undefined:一个声明后没有被赋值的变量会有一个默认值undefined ( 如果进行相连或者相加时,注意结果)
Null:一个声明变量给 null 值,里面存的值为空
3. 获取变量数据类型
-
3.1 获取检测变量的数据类型
typeof 可用来获取检测变量的数据类型
不同类型的返回值:

-
3.2 字面量
字面量是在源代码中一个固定值的表示法,通俗来说,就是字面量表示如何表达这个值。 - 数字字面量:8, 9, 10
- 字符串字面量:‘黑马程序员’, “大前端”
- 布尔字面量:true,false
4. 数据类型转换
使用表单、prompt 获取过来的数据默认是字符串类型的,此时就不能直接简单的进行加法运算,而需要转换变量的数据类型。通俗来说,就是把一种数据类型的变量转换成另一种数据类型,通常会实现3种方式的转换:


- 注意 parseInt 和 parseFloat 单词的大小写,这2个是重点
- 隐式转换是我们在进行算数运算的时候,JS 自动转换了数据类型
案例1:计算年龄
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>计算年龄</title>
</head>
<body>
<script>
var year = prompt('请输入您的出生日期:');
var nowyear = new Date().getFullYear();
alert('当前的年份是:' + nowyear);
var age = nowyear - year;
alert('您的年龄是:' + age);
</script>
</body>
</html>
结果如图:
案例2:简单加法器
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>简单加法器</title>
</head>
<body>
<script>
var a = prompt('请输入第一个数:');
var b = prompt('请输入第二个数:');
//注意类型转换
var sum = parseFloat(a) + parseFloat(b);
alert('结果是:' + sum);
</script>
</body>
</html>
结果如图:

- 代表空、否定的值会被转换为 false ,如 ‘’、0、NaN、null、undefined
- 其余值都会被转换为 true
四、解释型语言和编译型语言
1. 概述
计算机不能直接理解任何除机器语言以外的语言,所以必须要把程序员所写的程序语言翻译成机器语言才能执行程序。程序语言翻译成机器语言的工具,被称为翻译器。

- 翻译器翻译的方式有两种:一个是编译,另外一个是解释。两种方式之间的区别在于翻译的时间点不同
- 编译器是在代码执行之前进行编译,生成中间代码文件
- 解释器是在运行时进行及时解释,并立即执行(当编译器以解释方式运行的时候,也称之为解释器)
2. 执行过程

类似于请客吃饭:
编译语言:首先把所有菜做好,才能上桌吃饭
解释语言:好比吃火锅,边吃边涮,同时进行
五、关键字和保留字
1. 标识符
标识(zhi)符:就是指开发人员为变量、属性、函数、参数取的名字。
标识符不能是关键字或保留字。
2. 关键字
关键字:是指 JS本身已经使用了的字,不能再用它们充当变量名、方法名。
包括:break、case、catch、continue、default、delete、do、else、finally、for、function、if、in、instanceof、new、return、switch、this、throw、try、typeof、var、void、while、with 等。
3. 保留字
保留字:实际上就是预留的“关键字”,意思是现在虽然还不是关键字,但是未来可能会成为关键字,同样不能使用它们当变量名或方法名。
包括:boolean、byte、char、class、const、debugger、double、enum、export、extends、fimal、float、goto、implements、import、int、interface、long、mative、package、private、protected、public、short、static、super、synchronized、throws、transient、volatile 等。
六、运算符(操作符)
1. 运算符的分类
运算符(operator)也被称为操作符,是用于实现赋值、比较和执行算数运算等功能的符号。
JavaScript中常用的运算符有:
- 算数运算符
- 递增和递减运算符
- 比较运算符
- 逻辑运算符
- 赋值运算符
2. 算数运算符
1)算术运算符概述
概念:算术运算使用的符号,用于执行两个变量或值的算术运算。

2)浮点数的精度问题
浮点数值的最高精度是 17 位小数,但在进行算术计算时其精确度远远不如整数。
var result = 0.1 + 0.2; // 结果不是 0.3,而是:0.30000000000000004
console.log(0.07 * 100); // 结果不是 7, 而是:7.000000000000001
所以:不要直接判断两个浮点数是否相等 !
3. 递增和递减运算符
1)递增和递减运算符概述
如果需要反复给数字变量添加或减去1,可以使用递增(++)和递减( – )运算符来完成。
2)递增运算符
- 前置递增运算符
++num 前置递增,就是自加1,类似于 num = num + 1,但是 ++num 写起来更简单。
使用口诀:先自加,后返回值
var num = 10;
alert(++num + 10); // 21
- 后置递增运算符
num++ 后置递增,就是自加1,类似于 num = num + 1 ,但是 num++ 写起来更简单。
使用口诀:先返回原值,后自加
var num = 10;
alert(10 + num++); // 20
4. 比较运算符
1. 比较运算符概述
概念:比较运算符(关系运算符)是两个数据进行比较时所使用的运算符,比较运算后,会返回一个布尔值(true / false)作为比较运算的结果。

2. 等号比较

5. 逻辑运算符
1. 逻辑运算符概述
概念:逻辑运算符是用来进行布尔值运算的运算符,其返回值也是布尔值。后面开发中经常用于多个条件的判断

2. 逻辑与&&
两边都是 true才返回 true,否则返回 false
3. 逻辑或 ||
两边都是 true才返回 true,否则返回 false
4. 逻辑非 !
逻辑非(!)也叫作取反符,用来取一个布尔值相反的值,如 true 的相反值是 false
5. 短路运算(逻辑中断)
短路运算的原理:当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值;
1)逻辑与
语法: 表达式1 && 表达式2
- 如果第一个表达式的值为真,则返回表达式2
- 如果第一个表达式的值为假,则返回表达式1
2)逻辑或
语法: 表达式1 || 表达式2
- 如果第一个表达式的值为真,则返回表达式1
- 如果第一个表达式的值为假,则返回表达式2
6. 赋值运算符
概念:用来把数据赋值给变量的运算符。

7. 运算符优先级

- 一元运算符里面的逻辑非优先级很高
- 逻辑与比逻辑或优先级高
七、 流程控制
1. 流程控制概念
在一个程序执行的过程中,各条代码的执行顺序对程序的结果是有直接影响的。很多时候我们要通过控制代码的执行顺序来实现我们要完成的功能。
简单理解:流程控制就是来控制代码按照一定结构顺序来执行
流程控制主要有三种结构,分别是顺序结构、分支结构和循环结构,代表三种代码执行的顺序。

2. 顺序流程控制
顺序结构是程序中最简单、最基本的流程控制,它没有特定的语法结构,程序会按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的。

3. 分支流程控制
1)分支结构
由上到下执行代码的过程中,根据不同的条件,执行不同的路径代码(执行代码多选一的过程),从而得到不同的结果

JS 语言提供了两种分支结构语句:if 语句、switch 语句
- if 语句
a. 语法结构
// 条件成立执行代码,否则什么也不做
if (条件表达式) {
// 条件成立执行的代码语句
}
b. 执行流程

- if else语句(双分支语句)
a. 语法结构
// 条件成立 执行 if 里面代码,否则执行else 里面的代码
if (条件表达式) {
// [如果] 条件成立执行的代码
} else {
// [否则] 执行的代码
}
b. 执行流程

案例1:进入网吧
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>进入网吧</title>
</head>
<body>
<script>
var age = prompt('请输入您的年龄:');
if (age >= 18) {
alert('欢迎进入网吧!');
} else {
alert('未成年人禁止进入网吧!');
}
</script>
</body>
</html>
结果如图:
案例2:判断闰年
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>判断闰年</title>
</head>
<body>
<script>
var year = prompt('请输入要检测的年份');
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
alert('您输入的是闰年');
} else {
alert('您输入的是平年');
}
</script>
</body>
</html>
结果如图:
- if else if 语句(多分支语句)
- a. 语法结构
// 适合于检查多重条件。
if (条件表达式1) {
语句1;
} else if (条件表达式2) {
语句2;
} else if (条件表达式3) {
语句3;
....
} else {
// 上述条件都不成立执行此处代码
}
案例:判断成绩级别
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>判断成绩级别</title>
</head>
<body>
<script>
var score = prompt('请输入您的分数:');
if (score >= 90) {
alert('您的等级是A');
} else if (score >= 80) {
alert('您的等级是B');
} else if (score >= 70) {
alert('您的等级是C');
} else if (score >= 60) {
alert('您的等级是D');
} else {
alert('您的等级是E');
}
</script>
</body>
</html>
结果如图:
- a. 执行逻辑

3. 三元表达式
1)语法结构
表达式1 ? 表达式2 : 表达式3;
2)执行思路
- 如果表达式1为 true ,则返回表达式2的值,如果表达式1为 false,则返回表达式3的值
- 简单理解: 就类似于 if else (双分支) 的简写
案例:数字补0
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数字补0</title>
</head>
<body>
<script>
var time = prompt('请输入一个0~59之间的数字:');
var result = time < 10 ? '0' + time : time;
alert(result);
</script>
</body>
</html>
结果如图:
4. switch分支流程控制
1)语法结构
switch 语句也是多分支语句,它用于基于不同的条件来执行不同的代码。当要针对变量设置一系列的特定值的选项时,就可以使用 switch。
switch( 表达式 ){
case value1:
// 表达式 等于 value1 时要执行的代码
break;
case value2:
// 表达式 等于 value2 时要执行的代码
break;
default:
// 表达式 不等于任何一个 value 时要执行的代码
}
-
关键字 switch 后面括号内可以是表达式或值, 通常是一个变量
-
关键字 case , 后跟一个选项的表达式或值,后面跟一个冒号
-
switch 表达式的值会与结构中的 case 的值做比较
-
如果存在匹配全等(===) ,则与该 case 关联的代码块会被执行,并在遇到 break 时停止,整个 switch 语句代码执行结束
-
如果所有的 case 的值都和表达式的值不匹配,则执行 default 里的代码
注意: 执行case 里面的语句时,如果没有break,则继续执行下一个case里面的语句。
案例:查询水果
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>查询水果</title>
</head>
<body>
<script>
var fruit = prompt('请输入您查询的水果:');
switch (fruit) {
case '苹果':
alert('苹果的价格是3.5/斤');
break;
case '橘子':
alert('橘子的价格是8.5/斤');
break;
case '香蕉':
alert('香蕉的价格是1.5/斤');
break;
default:
alert('没有此水果');
}
</script>
</body>
</html>
结果如图:
2)switch 语句和 if else if 语句的区别
- 一般情况下,它们两个语句可以相互替换
- switch…case 语句通常处理 case为比较确定值的情况, 而 if…else…语句更加灵活,常用于范围判断(大于、等于某个范围)
- switch 语句进行条件判断后直接执行到程序的条件语句,效率更高。而if…else 语句有几种条件,就得判断多少次。
- 当分支比较少时,if… else语句的执行效率比 switch语句高。
- 当分支比较多时,switch语句的执行效率比较高,而且结构更清晰。
五、循环
1. for循环
for(初始化变量; 条件表达式; 操作表达式 ){
//循环体
}
案例1:求1~100之间所有数的平均值
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>求1~100之间所有数的平均值</title>
</head>
<body>
<script>
var sum = 0,
avg = 0;
for (var i = 1; i <= 100; i++) {
sum += i;
}
avg = sum / 100;
console.log('1~100之间所有数的平均值为' + avg);
</script>
</body>
</html>
结果如图:
案例2:求1~100之间所有偶数和、奇数和
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>求1~100之间所有偶数和、奇数和</title>
</head>
<body>
<script>
var even = 0,
odd = 0;
for (var i = 1; i <= 100; i++) {
if (i % 2 == 0) {
even += i;
} else {
odd += i;
}
}
console.log('1~100之间所有偶数和为' + even);
console.log('1~100之间所有奇数和为' + odd);
</script>
</body>
</html>
结果如图:
案例3:求1~100之间所有偶数和、奇数和
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>求1~100之间所有能被3整除的数字的和</title>
</head>
<body>
<script>
var sum = 0;
for (var i = 1; i <= 100; i++) {
if (i % 3 == 0) {
sum += i;
}
}
console.log('1~100之间所有能被3整除的数字的和为' + sum);
</script>
</body>
</html>
结果如图:
案例4:求学生成绩
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>求学生成绩</title>
</head>
<body>
<script>
var sum = 0,
avg = 0;
var num = prompt('请输入班级人数:');
for (var i = 1; i <= num; i++) {
var score = prompt('请输入第' + i + '个学生的成绩');
sum += parseFloat(score);
}
avg = sum / num;
alert('总成绩是:' + sum);
alert('平均成绩是:' + avg);
</script>
</body>
</html>
结果如图:
案例5:一行打印五个星星
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>一行打印五个星星</title>
</head>
<body>
<script>
var str = '';
for (var i = 0; i < 5; i++) {
str += '★';
}
console.log(str);
</script>
</body>
</html>
结果如图:
2. 双重for循环:外层循环一次,内层for循环全部执行
for (外循环的初始; 外循环的条件; 外循环的操作表达式) {
for (内循环的初始; 内循环的条件; 内循环的操作表达式) {
需执行的代码;
}
}
案例1:打印五行五列星星
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>打印五行五列星星</title>
</head>
<body>
<script>
var str = '';
for (var i = 0; i < 5; i++) {
for (var j = 0; j < 5; j++) {
str = str + '★';
}
str = str + '\n';
}
console.log(str);
</script>
</body>
</html>
1.内层循环负责一行打印五个星星
2.外层循环负责打印五行
结果如图:
案例2:打印n行n列的星星
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>打印n行n列的星星</title>
</head>
<body>
<script>
var str = '';
var rows = prompt('请您输入行数:');
var cols = prompt('请您输入列数:');
for (var i = 0; i < rows; i++) {
for (var j = 0; j < cols; j++) {
str += '★';
}
str += '\n';
}
console.log(str);
</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>打印倒三角形</title>
</head>
<body>
<script>
var str = '';
for (var i = 0; i < 10; i++) {
for (var j = i; j < 10; j++) {
str = str + '★';
}
str = str + '\n';
}
console.log(str);
</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>九九乘法表</title>
</head>
<body>
<script>
var str = '';
for (var i = 1; i <= 9; i++) {
for (var j = 1; j <= i; j++) {
str = str + j + '×' + i + '=' + i * j
}
str = str + '\n';
}
console.log(str);
</script>
</body>
</html>
结果如图:
3. while循环
语法结构
当条件表达式为真时,则执行循环体,否则退出循环
while (条件表达式) {
// 循环体代码
}
案例1:打印人的一生,从1岁到100岁
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>打印人的一生,从1岁到100岁</title>
</head>
<body>
<script>
var i = 1;
while (i <= 100) {
console.log('这个人今年' + i + '岁了');
i++;
}
</script>
</body>
</html>
结果如图:
案例2:计算1~100之间所有整数的和
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>计算1~100之间所有整数的和</title>
</head>
<body>
<script>
var sum = 0;
var i = 1;
while (i <= 100) {
sum += i;
i++;
}
console.log('1~100之间所有整数的和为:' + sum);
</script>
</body>
</html>
结果如图:
案例3:弹出一个提示框,你爱我吗?如果输入我爱你,就提示结束,否则一直询问
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>弹出一个提示框,你爱我吗?如果输入我爱你,就提示结束,否则一直询问</title>
</head>
<body>
<script>
var result = prompt('你爱我吗?');
while (result !== '我爱你') {
result = prompt('你爱我吗?');
}
alert('我也爱你啊');
</script>
</body>
</html>
结果如图:
4. do-while循环
语法结构
先执行一次循环体,再判断条件,如果条件表达式结果为真,则继续执行循环体,否则退出循环
do {
// 循环体代码 - 条件表达式为 true 时重复执行循环体代码
} while(条件表达式);
案例1:打印人的一生,从1岁到100岁
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>打印人的一生,从1岁到100岁</title>
</head>
<body>
<script>
var age = 1;
do {
console.log('这个人今年' + age + '岁了');
age++;
} while (age <= 100)
</script>
</body>
</html>
结果如图:
案例2:计算1~100之间所有整数的和
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>计算1~100之间所有整数的和</title>
</head>
<body>
<script>
var sum = 0,
i = 1;
do {
sum += i;
i++;
} while (i <= 100)
console.log('1~100之间所有整数的和为:' + sum);
</script>
</body>
</html>
结果如图:
案例3:弹出一个提示框,你爱我吗?如果输入我爱你,就提示结束,否则一直询问
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>弹出一个提示框,你爱我吗?如果输入我爱你,就提示结束,否则一直询问</title>
</head>
<body>
<script>
do {
var result = prompt('你爱我吗?');
} while (result !== '我爱你')
alert('我也爱你啊');
</script>
</body>
</html>
结果如图:
5. 循环小结
- JS中循环有for、while、do while
- 三种循环很多情况下都可以相互替代使用
- 如果是用来记次数,跟数字相关的,三者使用基本相同,但是我们更喜欢用for
- while和do…while可以做更复杂的判断条件,比for循环要更灵活一些
- 实际工作中,我们更常用for循环语句,因为它写法更简洁直观
6. continue、break
- continue:用于立即跳出本次循环,继续下一次循环(本次循环体中 continue 之后的代码就会少执行一次)。
- break:用于立即跳出整个循环(循环结束)。
P.s:
综合案例1:简易ATM
//用switch实现
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>简易ATM(用switch实现)</title>
</head>
<body>
<script>
var bal = 100;
var opt = prompt('请输入您要的操作:\n1.存钱\n2.取钱\n3.显示余额\n4.退出\n');
switch (parseInt(opt)) {
case 1:
var save = prompt('请输入您要存的钱数:');
bal += parseFloat(save);
alert('您的余额为:' + bal);
break;
case 2:
var withdraw = prompt('请输入您要取的钱数:');
bal -= withdraw;
alert('您的余额为:' + bal);
break;
case 3:
alert('您的余额为:' + bal);
break;
case 4:
alert('您已退出系统,欢迎下次使用,再见!');
break;
default:
alert('输入错误,请重新输入');
break;
}
</script>
</body>
</html>
//用if else实现
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>简易ATM(用if else实现)</title>
</head>
<body>
<script>
var bal = 100;
var opt = prompt('请输入您要的操作:\n1.存钱\n2.取钱\n3.显示余额\n4.退出\n');
if (opt == 1) {
var save = prompt('请输入您要存的钱数:');
bal += parseFloat(save);
alert('您的余额为:' + bal);
} else if (opt == 2) {
var withdraw = prompt('请输入您要取的钱数:');
bal -= withdraw;
alert('您的余额为:' + bal);
} else if (opt == 3) {
alert('您的余额为:' + bal);
} else if (opt == 4) {
alert('您已退出系统,欢迎下次使用,再见!');
} else {
alert('输入错误,请重新输入');
}
</script>
</body>
</html>
结果如图:
综合案例2:从1开始第35个能被7和3整除的数
//用for循环实现
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>从1开始第35个能被7和3整除的数(用for循环实现)</title>
</head>
<body>
<script>
var num = 1,
count = 0,
result = 0;
for (var i = 1; i <= num; i++) {
num++;
if (i % 3 == 0 && i % 7 == 0) {
result = i
count++;
console.log('从1开始第' + count + '个能被7和3整除的整数是' + result);
} else if (count == 35) {
break;
}
}
console.log('从1开始第35个能被7和3整除的整数是' + result);
</script>
</body>
</html>
//用while循环实现
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>从1开始第35个能被7和3整除的数</title>
</head>
<body>
<script>
var num = 1,
count = 0,
result = 0;
while (count < 35) {
num++;
if (num % 3 == 0 && num % 7 == 0) {
result = num;
count++;
console.log('从1开始第' + count + '个能被7和3整除的整数是' + result);
}
}
console.log('从1开始第35个能被7和3整除的整数是' + result);
</script>
</body>
</html>
结果如图:
八、 数组
1. 数组的概念
- 数组可以把一组相关的数据一起存放,并提供方便的访问(获取)方式。
- 数组是指一组数据的集合,其中的每个数据被称作元素,在数组中可以存放任意类型的元素。数组是一种将一组数据存储在单个变量名下的优雅方式。
2. 创建数组
JS 中创建数组有两种方式:
1)利用 new 创建数组
var arr = new Array(); // 创建一个新的空数组
2)利用数组字面量创建数组
//使用数组字面量方式创建空的数组
var 数组名 = [];
数组的字面量是方括号 [ ]
声明数组并赋值称为数组的初始化
这种字面量方式也是我们以后最多使用的方式
3)数组元素的类型
数组中可以存放任意类型的数据,例如字符串,数字,布尔值等。
//使用数组字面量方式创建带初始值的数组
var 数组名 = ['1','2','true','绿色'];
3. 获取数组中的元素
索引(下标):用来访问数组元素的序号(数组下标从0开始)。

数组可以通过索引来访问(得到)、设置、修改对应的数组元素,我们可以通过"数组名[索引]"的形式来获取数组中的元素。
案例:数组练习
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数组练习</title>
</head>
<body>
<script>
var arr = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'];
console.log(arr[6]);
</script>
</body>
</html>
结果如图:
4. 遍历数组
1)数组遍历
把数组中的每个元素从头到尾都访问一次(类似学生的点名),可以通过 for 循环索引遍历数组中的每一项
var arr = ['red','green', 'blue'];
for(var i = 0; i < arr.length; i++){
console.log(arr[i]);
}
2)数组的长度
默认情况下表示数组中元素的个数,使用“数组名.length”可以访问数组元素的数量(数组长度)。
var arrStus = [1,2,3];
alert(arrStus.length); // 3
案例1:遍历数组
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>遍历数组</title>
</head>
<body>
<script>
var arr = ['关羽', '张飞', '赵云', '黄忠', '刘备', '姜维'];
for (i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
</script>
</body>
</html>
结果如图:
案例2:数组求和及平均值
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数组求和及平均值</title>
</head>
<body>
<script>
var sum = 0,
avg = 0;
var arr = [2, 6, 1, 7, 4];
var len = arr.length;
for (var i = 0; i < len; i++) {
sum += arr[i];
}
avg = sum / len;
console.log('数组的和为:' + sum, '数组的平均值为:' + avg);
</script>
</body>
</html>
结果如图:
案例3:数组最大值
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数组最大值</title>
</head>
<body>
<script>
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);
</script>
</body>
</html>
结果如图:
案例4:数组转换为分割字符串
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数组转换为分割字符串</title>
</head>
<body>
<script>
var str = '',
sep = '|';
var arr = ['red', 'green', 'blue', 'pink'];
for (var i = 0; i < arr.length; i++) {
str += arr[i] + sep;
}
console.log('转换为字符串为:' + str);
</script>
</body>
</html>
结果如图:
5. 数组中新增元素
可以通过修改length长度以及索引号增加数组元素
1)通过修改length长度新增数组元素
- 可以通过修改length长度来实现数组扩容的目的
- length属性是可读写的
var arr = ['red', 'green', 'blue', 'pink'];
arr.length = 6;
console.log(arr);
console.log(arr[4]); //undefined
声明变量未给值,默认值就是undefined
2)通过修改数组索引新增数组元素(最常用的方式)
- 可以通过修改数组索引的方式追加数组元素
- 不能直接给数组名赋值,否则会覆盖掉以前的数据
var arr = ['red', 'green', 'blue', 'pink'];
arr[4] = 'yellow';
console.log(arr);
案例1:数组存放1~10个值
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>筛选数组</title>
</head>
<body>
<script>
var arr = [];
for (var i = 0; i < 10; i++) {
arr[i] = i + 1;
}
console.log(arr);
</script>
</body>
</html>
结果如图:
案例2:筛选数组
//方法一
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>筛选数组</title>
</head>
<body>
<script>
var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
var newArr = [];
var count = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] >= 10) {
newArr[count] = arr[i];
// 新数组索引号应该从0开始,依次递增
count++;
}
}
console.log(newArr);
</script>
</body>
</html>
//方法二
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>筛选数组</title>
</head>
<body>
<script>
var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
var newArr = [];
// 刚开始newArr.length是0
for (var i = 0; i < arr.length; i++) {
if (arr[i] >= 10) {
newArr[newArr.length] = arr[i];
}
}
console.log(newArr);
</script>
</body>
</html>
结果如图:
综合案例1:数组去重(删除指定数组元素)
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>删除指定数组元素</title>
</head>
<body>
<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>
</body>
</html>
结果如图:
综合案例2:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>翻转数组</title>
</head>
<body>
<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>
</body>
</html>
结果如图:
综合案例3:数组排序(冒泡排序)(重点掌握)
冒泡排序:是一种算法,把一系列的数据按照一定的顺序进行排列显示(从小到大或从大到小)。
冒泡排序是一种简单的排序算法,它重复地走访要排序地数列,一次比较两个元素,如果他们地顺序错误就把他们交换过来,走访数列地工作是重复地进行直到没有再需要交换的,也就是说该数列已经排序完成,这个算法地名字由来是因为越小的元素会经由交换慢慢"浮"到数列地顶端。

<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>冒泡排序</title>
</head>
<body>
<script>
var arr = [4, 1, 3, 2, 5];
for (var i = 0; i <= arr.length - 1; i++) { // 外层循环管趟数
for (var j = 0; j < arr.length - i - 1; j++) // 内层循环管每趟的交换次数
// 内部交换2个变量的值,前一个和后面一个数组元素相比较
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
console.log(arr);
</script>
</body>
</html>
结果如图:
九、 函数
1. 函数的概念
函数:就是封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量代码的重复使用。
2. 函数的使用
1)声明函数
// 声明函数
function 函数名() {
//函数体代码
}
- function是声明函数的关键字,必须小写
- 函数是做某件事情,函数名一般是动词,如sayHi
- 函数不调用,自己不执行
2)调用函数
// 调用函数
函数名(); // 通过调用函数名来执行函数体代码
- 调用的时候千万不要忘记添加小括号
- 口诀:函数不调用,自己不执行
注意:声明函数本身并不会执行代码,只有调用函数时才会执行函数体代码。
3)函数的封装
- 函数的封装是把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口,可以简单理解为封装类似于将电脑配件整合组装到机箱中 ( 类似快递打包)
案例1:利用函数计算1~100之间的累加和
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>利用函数计算1~100之间的累加和</title>
</head>
<body>
<script>
// 1. 声明函数
function getSum() {
var sum = 0;
for (var i = 1; i <= 100; i++) {
sum += i;
}
console.log(sum);
}
// 2. 调用函数
getSum();
</script>
</body>
</html>
结果如图:
3. 函数的参数
1)形参和实参
在声明函数时,可以在函数名称后面的小括号中添加一些参数,这些参数被称为形参,形参可以看做是不用声明的变量,默认是undefined;
而在调用该函数时,同样也需要传递相应的参数,这些参数被称为实参。

// 带参数的函数声明
function 函数名(形参1, 形参2 , 形参3...) { // 可以定义任意多的 参数,用逗号分隔
// 函数体
}
// 带参数的函数调用
函数名(实参1, 实参2, 实参3...);
案例:利用函数求任意两个数的和
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>利用函数求任意两个数的和</title>
</head>
<body>
<script>
// 利用函数求任意两个数的和
function getSum(num1, num2) {
console.log(num1 + num2);
}
// 利用函数求任意两个数之间的和
function getSums(start, end) {
var sum = 0;
for (var i = start; i <= end; i++) {
sum += i;
}
console.log(sum);
}
getSum(1, 3);
getSums(1, 100);
</script>
</body>
</html>
结果如图:
2)函数形参和实参个数不匹配问题

function getSum(num1, num2) {
console.log(num1 + num2);
}
getSum(100, 200); //形参和实参个数相等,输出正确结果
getSum(100, 200, 300); // 实参个数多于形参,只取到形参的个数
getSum(200); //实参个数少于形参,多的形参定义为undefined,结果为NaN
结果如图:
3)小结
- 函数可以带参数也可以不带参数
- 声明函数的时候,函数名括号里面的是形参,形参的默认值为 undefined
- 调用函数的时候,函数名括号里面的是实参
- 多个参数中间用逗号分隔
- 形参的个数可以和实参个数不匹配,但是结果不可预计,我们尽量要匹配
4. 函数的返回值
1)return语句
有的时候,我们会希望函数将值返回给调用者,此时通过使用return语句就可以实现。
// 声明函数
function 函数名(){
...
return 需要返回的值;
}
// 调用函数
函数名(); // 此时调用函数就可以得到函数体内return 后面的值
- 我们的函数只是实现某种功能,最终的结果需要返回给函数的调用者函数名() 通过return实现的
- 只要函数遇到return,就把后面的结果返回给函数的调用者,函数名()=return后面的结果
案例1:利用函数求两个数的最大值
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>利用函数求两个数的最大值</title>
</head>
<body>
<script>
function getMax(num1, num2) {
if (num1 > num2) {
return num1;
} else {
return num2;
}
// 方法二: 三元表达式
//return num1 > num2 ? num1 : num2;
}
console.log(getMax(1, 3));
</script>
</body>
</html>
结果如图:
案例2:利用函数求两个数的最大值
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>利用函数求数组的最大值</title>
</head>
<body>
<script>
function getArrMax(arr) { // arr接收一个数组 arr=[5, 2, 99, 101, 67, 77]
var max = arr[0];
for (var i = 1; i <= arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
// 在实际开发中,我们经常用一个变量来接收函数的返回结果,使用更简单
var re = getArrMax([5, 2, 99, 101, 67, 77]); //实参是一个数组送过去
console.log(re);
</script>
</body>
</html>
结果如图:
2)return终止函数
3)return的返回值
4)函数没有return返回undefined
函数都是有返回值的
5)break、continue、return的区别
- break:结束当前的循环体(如for、while)
- continue:跳出本次循环,继续执行下次循环(如for、while)
- return:不仅可以退出循环,还能够返回return语句中的值,同时还可以结束当前的函数体内的代码
4. 通过榨汁机看透函数

练习1:写一个函数,用户输入任意两个数字的任意算术运算(简单的计算器小功能),并能弹出运算后的结果
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>homework1</title>
</head>
<body>
<script>
function calculate(num1, num2, opt) {
switch (opt) {
case '+':
return parseFloat(num1) + parseFloat(num2);
case '-':
return num1 - num2;
case '*':
return num1 * num2;
case '/':
return num1 / num2;
default:
alert('输入错误,请重新输入!');
}
}
var num1 = prompt('请输入第一个数:');
var num2 = prompt('请输入第二个数字:');
var opt = prompt('请输入运算符号:');
var result = calculate(num1, num2, opt);
alert('计算出的结果是:' + result);
</script>
</body>
</html>
结果如图:
练习2:写一个函数,用户输入任意两个数字,得出最大值,并能弹出结果
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>homework2</title>
</head>
<body>
<script>
function getMax(num1, num2) {
if (parseFloat(num1) > parseFloat(num2)) {
return num1;
} else {
return num2;
}
}
var num1 = prompt('请输入第一个数:');
var num2 = prompt('请输入第二个数字:');
var max = getMax(num1, num2);
alert('最大值是:' + max);
</script>
</body>
</html>
结果如图:
练习3:写一个函数,用户输入任意三个不同数字,得出最大值,并能弹出结果
// 非冒泡排序法
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>homework3</title>
</head>
<body>
<script>
function getMax(num1, num2, num3) {
var max = parseFloat(num1);
if (parseFloat(num2) > max) {
max = num2;
}
if (parseFloat(num3) > max) {
max = num3;
}
return max;
}
var num1 = prompt('请输入第一个数:');
var num2 = prompt('请输入第二个数字:');
var num3 = prompt('请输入第三个数字:');
var max = getMax(num1, num2, num3);
alert('最大值是:' + max);
</script>
</body>
</html>
结果如图:
练习4:写一个函数,用户输入一个数,判断是否是素数(又叫质数,只能被1和自身整除的数),并弹出返回值
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>homework4</title>
</head>
<body>
<script>
function isPrime(num) {
var count = 0;
for (var i = 1; i <= num; i++) {
if (num % i == 0) {
count++;
}
}
if (count == 2) {
return '是质数';
} else {
return '不是质数';
}
}
var num = prompt('请输入第一个数:');
var result = isPrime(num);
alert(result);
</script>
</body>
</html>
结果如图:
5. arguments的使用
当不确定有多少个参数传递的时候,可以用 arguments 来获取。在JavaScript 中,arguments实际上它是当前函数的一个内置对象。所有函数都内置了一个 arguments 对象,arguments 对象中存储了传递的所有实参。
arguments展示形式是一个伪数组,因此可以进行遍历。伪数组并不是真正意义上的数组,具有以下特点:
- 具有数组的length 属性
- 按照索引方式储存数据
- 不具有真正数组的一些方法:push()、pop() 等
注意:在函数内部使用该对象,用此对象获取函数调用时传的实参。
// arguments的使用,只有函数才有arguments对象,而且是每个函数都内置好了这个arguments对象
function fn() {
console.log(arguments); // 里面存储了所有传递过来的实参 arguments = [1,2,3]
console.length();
console.log(arguments[2]);
// 我们可以按照数组的方式遍历arguments
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
案例:利用函数求任意个数的最大值
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>利用函数求任意个数的最大值</title>
</head>
<body>
<script>
function getMax() {
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(1, 2, 4, 5, 6));
console.log('最大值是:' + getMax(1, 2, 45, 66, 7, 93));
</script>
</body>
</html>
结果如图:
综合案例1:利用函数封装方式,翻转任意一个数组

<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>利用函数封装方式,翻转任意一个数组</title>
</head>
<body>
<script>
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, 2, 3, 4, 5]);
console.log(arr1);
</script>
</body>
</html>
结果如图:
综合案例2:利用函数封装方式,对数组排序,冒泡排序

<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>利用函数封装方式,翻转任意一个数组</title>
</head>
<body>
<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, 6, 2, 9]);
console.log(arr1);
</script>
</body>
</html>
结果如图:
综合案例3:判断闰年
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>判断闰年</title>
</head>
<body>
<script>
function isLeapYear(year) {
var flag = false;
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
flag = true;
} else
flag = false;
return flag;
}
console.log(isLeapYear(2000));
</script>
</body>
</html>
结果如图:
6. 函数案例
函数可以调用另外一个函数
因为每个函数都是独立的代码块,用于完成特殊任务,因此经常会用到函数相互调用的情况。

// 函数是可以相互调用的
function fn1(){
console.log(11);
fn2(); // 在fn1函数里面调用了fn2函数
}
fn1();
function fn2(){
console.log(22);
}
综合案例4:用户输入年份,输出当前月份2月份的天数
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用户输入年份,输出当前月份2月份的天数</title>
</head>
<body>
<script>
function isLeapYear(year) {
var flag = false;
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
flag = true;
} else
flag = false;
return flag;
}
function getDays() {
var year = prompt('请您输入年份:');
var days = 0;
if (isLeapYear(year)) {
days = 29;
} else {
days = 28;
}
return days;
}
alert('当年年份的2月份有' + getDays() + '天');
</script>
</body>
</html>
7. 函数的两种声明方式
1)利用函数关键字自定义函数(命名函数)
// 声明定义方式
function fn() {...}
// 调用
fn();
- 因为有名字,所以也被称为命名函数
- 调用函数的代码既可以放到声明函数的前面,也可以放在声明函数的后面
2)函数表达式(匿名函数)
// 这是函数表达式写法,匿名函数后面跟分号结束
var fn = function(aru){...};
cosole.log('我是函数表达式'); // 调用的方式,函数调用必须写到函数体下面
cosole.log(aru);
fn('参数');
- fn是变量名,不是函数名
- 函数表达式声明方式跟声明变量差不多,只不过变量里面存的是值,而函数表达式里面存的是函数
- 函数表达式也可以进行参数传递
- 函数调用的代码必须写到函数体后面
十、 Javascript作用域
1. 作用域
1)定义
Javascript作用域:就是代码(变量)在某个范围内起作用和效果,目的是为了提高程序的可靠性更重要的是减少命名冲突。
2)js的作用域(es6之前):全局作用域 和 局部作用域
3)全局作用域:整个script标签或者是一个单独的js文件
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>
// 全局作用域
var num=10;
console.log(num);
function fn(){
// 局部作用域
var num=20;
console.log(num);
}
fn();
</script>
</body>
</html>
结果如图:
2. 变量的作用域
1)变量作用域的分类
在Javascript中,根据作用域的不同,变量可以分为两种:
- 全局变量
- 局部变量
2)全局变量
在全局作用域下声明的变量叫做全局变量(在函数外部定义的变量)。
- 全局变量在代码的任何位置都可以使用
- 特殊情况下,在函数内不使用var声明直接赋值的变量也是全局变量(不建议使用)。
3)局部变量
在局部作用域下声明的变量叫做局部变量(在函数内部定义的变量)
- 局部变量只能在函数内部使用
- 函数的形参实际上就是局部变量。
4)全局变量和局部变量的区别
- 全局变量:在任何一个地方都可以使用,只有在浏览器关闭时才会被销毁,因此比较占内存资源
- 局部变量:只在函数内部使用,当其所在的代码块被执行时,会被初始化;当代码块运行结束后,就会被销毁,因此更节省内存空间。
5)Javascript没有块级作用域(了解)
js中没有块级作用域,js的作用域:全局作用域、局部作用域,现阶段我们js没有块级作用域
我们js也是在es6的时候新增的块级作用域
块级作用域{ } if{ } for{ }
比如java中
// 外面的是不能调用num的
if(xx){
int num = 10;
}
4. 作用域链(就近原则)
- 只要是代码,就至少有一个作用域
- 写在函数内部的局部作用域
- 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
- 根据在内部函数可以访问外部函数的这种机制,用链式查找决定哪些数据能被内部访问,就称为作用域链,即就近原则。
案例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>
<script>
function f1() {
var num = 123;
function f2() {
console.log(num); // 站在目标出发,一层一层的往外寻找
}
f2();
}
var num = 456;
f1();
</script>
</head>
<body>
</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>
<script>
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); // a的值?
console.log(b); // b的值?
}
}
}
fn1();
</script>
</head>
<body>
</body>
</html>
结果如图
十、 Javascript作用域
1. JavaScript预解析
1)预解析
JavaScript代码是由浏览器中的JavaScript解析器来执行的。
js解析器在运行js代码时会分为两步:
- 预解析:js引擎会把js里面所有的var还有function提升到当前作用域的最前面,分为:
a. 变量预解析(变量提升):把所有的变量声明提升到当前的作用域最前面,不做赋值;
b. 函数预解析(函数提升):把所有的函数声明提升到当前作用域的最前面,不调用函数; - 代码执行:按照代码执行书写的顺序从上往下执行。
案例1:
console.log(num);
var num = 10;
// 相当于执行了以下代码,结果为undefined
// var num;
// console.log(num);
// num = 10;
案例2:
fn();
var fun = function(){
console.log(22);
}
// 相当于执行了以下代码,结果报错
// var fun;
// fun();
// fun = function(){
// cosole.log(22);
}
案例1:
var num = 10;
fun();
function fun(){
console.log(num);
var num = 20;
}
/* 相当于以下代码:
var num;
function fun(){
var num;
console.log(num);
num = 20;
}
num = 10;
fun();
*/
结果如图:
案例2:
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();
*/
结果如图:
案例3:
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();
*/
结果如图:
案例4:
f1();
console.log(c);
console.log(b);
console.log(a);
function f1(){
var a = b = c = 9;
console.log(a);
console.log(b);
console.log(c);
}
/* 相当于以下代码:
function f1(){
var a;
// 集体声明:var a = 9, b = 9, c=9;
// 相当于var a = 9; b = 9; c = 9; b和c直接赋值,没有var声明,当全局变量看
a = b = c = 9;
console.log(a);
console.log(b);
console.log(c);
}
f1();
console.log(c);
console.log(b);
console.log(a);
*/
结果如图:
十一、Javascript对象
1. 对象
1)什么是对象
现实生活中:万物皆对象,对象是一个具体的事物,看得见摸得着的实物,例如,一本书,一辆汽车,一个人可以是”对象“,一个数据库,一张网页,一个与远程服务器的连接也可以是对象。
在Javascript中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。
对象是由属性和方法组成的。
- 属性:事物的特征,在对象中用属性来表示(常用名词)
- 方法:事物的行为,在对象中用方法来表示(常用动词)
2)为什么需要对象
保存一个值时,可以使用变量,保存多个值(一组值)时,可以使用数组,但是要保存一个人的完整信息时,表达的含义就不那么明确,如:
var arr = {'米奇', '女',‘6’};
JS中的对象表达式结构表达更清晰,更强大。如保存一个人的完整信息:
// 伪代码
米奇.姓名 = ‘米奇’;
米奇.性别 = ‘女’;
米奇.年龄= ‘6’;
// 代码
person.name = '米奇';
person.sex = '女';
person.age = '6';
2. 创建对象的三种方式
在Javascript中,现阶段我们可以采用三种方式构建对象(object):
1) 利用字面量创建对象
1. 创建对象
对象字面量:花括号{ }里面包含了表达这个具体事物(对象)的属性和方法
// 利用对象字面量创建对象
// var obj = {}; // 创建了一个空的对象
var obj = {
sex = '女',
age: 6,
sayHi: function(){
alert('hello~');
}
}
2. 使用对象
1. 调用对象的属性
- 方法一:对象名.属性名 ,小点理解为”的“
console.log(obj.username);
- 方法二:对象名[‘属性名’],方括号里属性必须加引号
console.log(obj['age']);
2. 调用对象的方法:
对象名.方法名 ,方法名后面必须加括号
obj.sayHi();
3. 使用对象变量、属性、函数、方法总结
- 变量和属性
- 相同点:都是用来存储数据的
- 不同点:
- 变量:单独声明并赋值,单独存在,使用的时候直接写变量名
- 属性:在对象里面的变量,不需要声明,使用的时候必须是对象.属性,用来描述对象的特征
- 函数和方法
- 相同点:都是实现某种功能,做某件事
- 不同点:
- 函数:单独存在的,调用方式是函数名()
- 方法:在对象里面的函数,不需要声明,调用方式是对象.方法(),用来描述对象的行为和功能
2) 利用new object创建对象
1. 创建对象
// 利用new Object创建对象
var obj = new Object(); // 创建了一个空的对象
obj.username = '米奇';
obj.sex = '女';
obj.age = '6';
obj.sayHi = function(){
alert.log('hi~');
}
console.log(obj.username);
console.log(obj['sex']);
obj.sayHi();
- 添加对象的属性和方法,是利用等号 = 赋值的方法
- 每个属性和方法之间用分号结束
2. 使用对象
同利用字面量创建对象的方法
3) 利用构造函数创建对象
1. 为什么需要构造函数
因为前两种创建对象方式一次只能创建一个对象,一次创建一个对象,里面很多属性和方法是大量相同的,所以可以把对象里面一些相同的属性和方法抽象出来封装到函数里面。
构造函数:是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与new运算符一起使用,我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。
2. 创建和调用构造函数
// 创建构造函数
function Star(username, age, sex){
this.name = username;
this.age = age;
this.sex = sex;
this.sing = function(sang){
console.log(sang);
}
}
var mq = new Star('米奇', 6, '女');
// 调用构造函数返回的是一个对象
console.log(typeof mq);
console.log(mq.name);
console.log(mq['sex']);
mq.sing('冰雨');
-
1. 构造函数名字首字母要大写
-
2. 构造函数不需要return就可以返回结果
-
3. 调用构造函数必须使用new
-
4. 只要new Star()调用构造函数,就创建一个新的对象
-
5. 属性和方法的前面必须添加this
3. 构造函数和对象
- 构造函数:抽象了对象的公共部分,封装到了函数里面,它泛指某一大类(class),类似Java里的类(class)
- 创建对象:特指某一个,通过new关键字创建对象的过程我们也称为对象实例化
3. new关键字
new关键字在 执行时会做的四件事情:
1)new构造函数在内存中创建一个新的空对象
2)this就会指向刚才创建的新对象
3)执行构造函数里面的代码,给这个空对象添加属性和方法
4)返回这个新对象(所以构造函数里面不需要return)
记忆方法:
4. 遍历对象属性
for…in语句用于对数组或者对象的属性进行循环操作
语法格式:
for (变量 in 对象){
}
// 遍历对象
var obj = {
name: '米奇',
age: 6,
sex: '女'
}
for(var k in obj){
// 输出k得到的是属性名
console.log(k);
// 输出obj[k]得到的是属性值
console.log(obj[k]);
}
- for in里面的变量一般用k或key
小结:
1. 对象可以让代码结构更清晰
2. 对象复杂数据类型object
3. 本质:对象就是一组无序的相关属性和方法的集合
4. 构造函数泛指某一大类,比如苹果,不管是红色苹果还是绿色苹果,都统称为苹果
5. 对象实例特指一个事物,比如这个苹果
6. for…in语句用于对对象的属性进行循环操作
十二、Javascript对象
1)内置对象
- JavaScript中的对象分为3种:自定义对象、内置对象、浏览器对象
- 前面两种对象是JS基础内容,属于ECMAScript;第三个浏览器对象属于我们JS独有的
- 内置对象:指JS语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或是最基本而必要的功能(属性和方法)
- 内置对象最大的优点就是帮助我们快速开发
- JavaScript提供了多个内置对象:Math、Date、Array、String等
2)查文档
1. MDN
学习一个内置对象的使用,只要学会其常用成员的使用即可,我们可以通过查MDN/W3C文档来查询。
Mozilla开发者网络(MDN)提供了有关网络技术(Open Web)的信息,包括HTML、CSS和万维网及HTML5应用的API。
MDN:https://developer.mozilla.org/zh-CN/
2. 如何学习对象中的方法
3)Math对象
不是一个构造函数,所以我们不需要new来调用,而是直接使用里面的属性和方法即可。
// 圆周率
console.log(Math.PI);
// 最大值 99
console.log(Math.max(1, 99, 3));
// 字符串无法转换成数字 NaN
console.log(Math.max(1, 99, '米奇'));
// -Infinity
console.log(Math.max());
案例:利用对象封装自己的数学对象,里面有PI最大值和最小值
<!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>
// 利用对象封装自己的数学对象,里面有PI最大值和最小值
var myMath = {
PI: 3.1415926,
max: function(){
var max = arguments[0];
for(var i = 1;i<arguments.length;i++){
if(max < arguments[i]){
max = arguments[i];
}
}
return max;
},
min: function(){
var min = arguments[0];
for(var i = 0;i<arguments.length;i++){
if(min > arguments[i]){
min = arguments[i];
}
}
return min;
}
}
console.log(myMath.PI);
console.log(myMath.max(1, 2, 20));
console.log(myMath.min(8, 20, 3));
</script>
</body>
</html>
1. Math绝对值和三个取整方法
- Math.abs():绝对值
- Math.floor():地板,向下取整
- Math.ceil():天花板,向上取整
- Math.round():四舍五入,特殊情况.0.5时候往大取
2. 随机数方方法 random()
Math.random:
- 返回一个随机的小数,0<= x <1
- 方法里不跟参数
- 代码验证
- 我们想要得到两个数之间的随机整数,并且包含这2个整数:
Math.floor(Math.random() * (max - min +1)) + min;
function getRandom(min, max){
return Math.floor(Math.random() * (max - min +1)) + min;
}
console.log(getRandom(1, 10));
- 随机点名
var arr = ['张三', '李四', '王五'];
console.log(arr[getRandom(0,arr.length-1)]);
案例:程序随机生成一个1~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>
<script>
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var ran = getRandom(1, 10);
while (true) {
var num = prompt('请输入1~10之间的一个数字');
if (num > ran) {
alert('你猜大了');
} else if (num < ran) {
alert('你猜小了');
} else {
alert('恭喜你猜对了!');
break;
}
}
</script>
</head>
<body>
</body>
</html>
案例延伸:猜1~60之间的一个随机生成的整数,只有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>
<script>
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var ran = getRandom(1, 60);
for (var i = 0; i < 3; i++) {
var num = prompt('请输入1~60之间的一个数字');
if (num > ran) {
alert('你猜大了' + i);
} else if (num < ran) {
alert('你猜小了' + i);
} else {
alert('恭喜你猜对了!');
break;
}
}
alert('很遗憾你的10次机会用完了!');
</script>
</head>
<body>
</body>
</html>
4)Date对象
1. Date对象定义
Date对象和Math对象不一样,它是一个构造函数,必须使用new实例化后才能使用
- Date实例用来处理日期和时间
2. Date()方法的使用
- 获取当前时间必须实例化
var now = new Date();
cosole.log(new);
- Date()构造函数的参数
如果括号里有时间,就返回参数里的时间,例如日期格式字符串为’2020-01-01‘,可以写成new Date(‘2020-01-01’)或者new Date(‘2020-01-01’)
3. 日期格式化
- 年、月、日、星期
var date = new Date();
date.getFullYear():返回当前日期的年
date.getMonth():返回的是0~11月
date.getDate(): 返回的是几号
date.getDay(): 周日到周六返回的是0~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>
<script>
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth() + 1;
var dates = date.getDate();
var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
var day = date.getDay();
console.log('今天是:' + year + '年' + month + '月' + dates + '日' + arr[day]);
</script>
</head>
<body>
</body>
</html>
结果如图:
- 时、分、秒
var date = new Date();
date.getHours():返回时
date.getMinutes():返回分
date.getSeconds():返回秒
案例:输出当前时分秒
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
function getTime() {
var date = new Date();
var hour = date.getHours();
// 不满10在前面补一个0
hour = hour < 10 ? '0' + hour : hour;
var minute = date.getMinutes();
minute = minute < 10 ? '0' + minute : minute;
var second = date.getSeconds();
second = second < 10 ? '0' + second : second;
return hour + ':' + minute + ':' + second;
}
console.log(getTime());
</script>
</head>
<body>
</body>
</html>
结果如图:
4. 获取日期的总的毫秒形式
Date对象是基于1970年1月1日(世界标准时间)起的毫秒数
我们经常利用总的毫秒数来计算时间,因为它更精确
- 通过valueOf()/getTime()
var date = new Date();
date.valueOf()、date.getTime():返回当前时间距离1970.1.1总的毫秒数
- 简单写法(最常用)
var date = + new Date(); // 返回的就是总的毫秒数
- H5中新增的获得总的毫秒数
Date.now();
案例:倒计时效果(重点)

思路:
- 利用时间戳,用户输入时间总的毫秒数减去当前时间总的毫秒数,得到的就是剩余时间的毫秒数
- 再把剩余时间的毫秒数转换为天、时、分、秒:
// 转换为天、时、分、秒
day = parseInt(总秒数 / 60 / 60 / 24); // 计算天数
hour = parseInt(总秒数 / 60 / 60 % 24) //计算小时数
minute = parseInt(总秒数 / 60 / 60 % 60) // 计算分钟数
second = parseInt(总秒数 % 60) // 计算当前秒数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
function countDown(time) {
var nowTime = +new Date(); // 返回的是当前时间总的毫秒数
var inputTime = +new Date(time); // 返回的是用户输入时间总的毫秒数
var times = (inputTime - nowTime) / 1000; // time是剩余时间总的秒数
var d = parseInt(times / 60 / 60 / 24); // 天
d = d < 10 ? '0' + d : d;
var h = parseInt(times / 60 / 60 % 24); // 时
h = h < 10 ? '0' + h : h;
var m = parseInt(times / 60 % 60) // 分
m = m < 10 ? '0' + m : m;
var s = parseInt(times % 60) // 秒
s = s < 10 ? '0' + s : s;
return d + '天' + h + '时' + m + '分' + s + '秒';
}
console.log(countDown('2020-06-14 10: 00: 00'));
var date = new Date();
console.log(date);
</script>
</head>
<body>
</body>
</html>
结果如图:
5)数组对象
1. 数组对象的创建
创建数组对象的两种方式:
- 字面量方式
var arr = [1, 2, 3];
console.log(arr[0]);
- new Array()
var arr = new Array();
var arr1 = new Array(2); //创建了一个有两个空元素的数组
var arr2 = new Array(2, 3); //等价于[2, 3],表示里面有2个数组元素2,3
2. 检测是否为数组
- instanceof
var arr = [];
var obj = {};
console.log(arr instanceof Array);
console.log(obj instanceof Array);
结果如图:
- Array.isArray(参数):H5新增的方法,ie9以上版本支持
var arr = [];
var obj = {};
console.log(Array.isArray(arr));
console.log(Array.isArray(obj));
结果相同:
3. 添加或删除数组元素的方法

push() / unshift()
- 在数组 末尾( push() ) / 开头(unshift()) 增加一个或多个数组元素
- 参数直接写数组元素
- 返回的结果是新数组的长度
- 原数组也会发生变化
pop() / shift()
- 删除数组的最后一个( pop() )/第一个元素(shift()),一次只能删除一个元素
- 没有参数
- 返回的结果是删除的那个元素
- 原数组也会发生变化
案例:有一个包含工资的数组[1500, 1200, 2000, 2100, 1800],要求把数组中工资超过2000的删除,剩余的放到新数组里面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
var arr = [1500, 1200, 2000, 2100, 1800];
var newArr = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] < 2000) {
// newArr[newArr.length] = arr[i];
newArr.push(arr[i]);
}
}
console.log(newArr);
</script>
</head>
<body>
</body>
</html>
结果如图:
4. 数组排序

- 翻转数组:arr.reverse()
var arr = [13, 4, 7, 1, 77];
arr.reverse();
console.log(arr);
- 数组排序(冒泡排序):arr.sort()
var arr = [13, 4, 7, 1, 77];
arr.sort(function(a, b) {
return a - b; // 升序的顺序排列
return b - a; // 降序的顺序排列
});
console.log(arr);
5. 数组索引方法

indexOf() :从前往后 / lastIndexOf():从后往前
- 返回数组元素索引号方法
- 它只返回第一个满足条件的索引号
- 如果在该数组中找不到元素,则返回的是-1
var arr = ['red', 'green', 'blue', 'pink'];
console.log(arr.indexOf('blue'));
console.log(arr.lastIndexOf('blue'));
案例:数组去重(重点案例)
有一个数组[‘c’, ‘a’, ‘z’, ‘a’, ‘x’, ‘a’, ‘x’, ‘c’, ‘b’],要求去除数组中重复的元素。
分析:
- 目标:把旧数组里面不重复的元素选取出来放到数组中,重复的元素只保留一个,放到新数组中去重。
- 核心算法:我们遍历旧数组,然后拿着旧> 数组元素去查询新数组,如果该元素在新数组里面没有出现过,我们就添加,否则不添加
- 我们怎么知道该元素没有存在?利用新数组indexOf(数组元素)如果返回是-1就说明新数组里面没有该元素。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数组去重</title>
<script>
function unique(arr) {
var newArr = [];
for (var i = 0; i < arr.length; i++) {
if (newArr.indexOf(arr[i]) === -1) {
newArr.push(arr[i]);
}
}
return newArr;
}
var demo = unique([1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6]);
console.log(demo);
</script>
</head>
<body>
</body>
</html>
结果如图:
6. 数组转换为字符串

- toString()
var arr = [1, 2, 3];
cosole.log(arr.toString()); //1,2,3
- join(分隔符)
var arr = [1, 2, 3];
cosole.log(arr.join()); // 1,2,3
cosole.log(arr.join('-')); // 1-2-3
cosole.log(arr.join('&')); // 1&2&3
7. 其他常用方法

- concat()
var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
console.log(arr1.concat(arr2)); // [1, 2, 3, 4, 5, 6]
- slice(数组的下标小,数组的下标大)
var arr = [1, 2, 3, 4, 5, 6];
console.log(arr.slice(2, 4)); // [3, 4]
- splice(数组开始的下标,要删除的个数):会影响原数组
var arr = [1, 2, 3, 4, 5, 6];
console.log(arr.splice(0, 3)); // [1, 2, 3]
6)字符串对象
1. 基本包装类型
为了方便操作基本数据类型,JavaScript还提供了三个特殊的引用类型:String、Number和Boolean。
基本包装类型:把简单数据类型包装成为了复杂数据类型,这样基本数据类型就有了属性和方法
var str = 'andy';
console.log(str.length);
按道理基本数据类型是没有属性和方法的,而对象才有属性和方法,但上面的代码却可以执行,这是因为js会把基本数据类型包装成为复杂数据类型,其执行过程如下:
// 1. 生成临时变量,把简单数据类型包装成为复杂数据类型
var temp = new String('andy');
// 2. 把临时变量赋值给我们声明的字符串
str = temp;
// 3. 销毁临时变量
temp = null;
2. 字符串的不可变性
指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间
P.s:由于字符串的不可变性,大量拼接字符串的时候因为需要不断的开辟新的空间,所以会有效率问题
3. 根据字符串返回位置
字符串所有的方法,都不会修改字符串本身(字符串是不可变的,操作完成会返回一个新的字符串)。

str.indexOf(‘要查找的字符’,[起始的位置])
案例:返回字符位置
查找字符串"abcoefoxyozzopp"中所有o出现的位置以及次数。
- 核心算法:先查找第一个o出现的位置
- 然后,只要indexOf()返回的结果不是-1就继续往后查找
- 因为indexOf只能查找到第一个,所以后面的查找,利用第二个参数,当前索引加1,从而继续查找。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>返回字符位置(字符串)</title>
<script>
var str = 'abcoefoxyozzopp';
var index = str.indexOf('o');
var num = 0;
while (index !== -1) {
console.log(index);
num++;
index = str.indexOf('o', index + 1);
}
console.log('o出现的次数是:' + num);
</script>
</head>
<body>
</body>
</html>
结果如图:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>返回字符位置(数组)</title>
<script>
var str = ['red', 'blue', 'red', 'green', 'pink', 'red'];
var index = str.indexOf('red');
var num = 0;
while (index !== -1) {
console.log(index);
num++;
index = str.indexOf('red', index + 1);
}
console.log('red出现的次数是:' + num);
</script>
</head>
<body>
</body>
</html>
结果如图:
4. 根据位置返回字符(重点)

- str.charAt(index)
var str = 'andy';
console.log(str.charAt(3));
- charCodeAt(index): 返回相应索引号的字符ASCII值, 目的: 判断用户按下了哪个键
str.charAt(index)
console.log(str.charCodeAt[3]); // 97
- str[index]: H5新增的
console.log(str[0]); // a
案例:返回字符位置
判断一个字符串’abcoefoxyozzopp’中出现次数最多的字符,并统计其次数。
有一个对象来判断是否有该属性,对象[‘属性名’]
var o = {
age: 18;
}
if(o['sex']) {
console.log('里面有该属性');
} else {
console.log('里面没有该属性');
}
1. 核心算法:利用charAt()遍历该字符串
2. 把每个字符串都存储给对象,如果对象没有该属性,就为1,如果存在了就+1
3. 遍历对象,得到最大值和该字符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>返回字符位置</title>
<script>
var str = 'abcoefoxyozzopp';
var o = {};
for (var i = 0; i < str.length; i++) {
var chars = str.charAt(i); // chars是字符串的每一个字符
if (o[chars]) { // o[chars]得到的是属性值
o[chars]++;
} else {
o[chars] = 1
}
}
console.log(o);
// 遍历对象
var max = 0;
var ch = '';
for (var k in o) {
// k得到的是属性名
// o[k]得到的是属性值
if (o[k] > max) {
max = o[k];
ch = k;
}
}
console.log(max);
console.log('最多的字符是' + ch);
</script>
</head>
<body>
</body>
</html>
结果如图:
5. 字符串操作方法(重点)

6. 其他方法
- replace(‘被替换的字符’, ‘替换为的字符’):只会替换第一个字符
var str = 'andyandy';
console.log(str.replace('a' ,'b'));
案例:有一个字符串’abcoefoxyozzopp’,要求把里面所有的o替换为*
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>替换字符</title>
<script>
var str = 'abcoefoxyozzopp';
while (str.indexOf('o') !== -1) {
str = str.replace('o', '*');
}
console.log(str);
</script>
</head>
<body>
</body>
</html>
- split(‘分隔符’):字符转换为数组
var str = 'red, pink, blue';
console.log(str.split('&');
- toUpperCase():转换为大写
- toLowerCase():转换为小写
练习:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>练习</title>
<script>
var str = 'abaasdffggghhjjkkgfddsssss3444343';
// 1、字符串的长度
console.log('字符串的长度是:' + str.length);
// 2、取出指定位置的字符
function getStr(index) {
// var chars = str[index];
var chars = str.charAt(index);
return chars;
}
function isExist(ch) {
if (str.indexOf(ch) !== -1) {
console.log('该字符串存在');
} else {
console.log('该字符串不存在');
}
return ch;
}
function replaceStr(a, b) {
while (str.indexOf(a) !== -1) {
str = str.replace(a, b);
}
return str;
}
function subStr(a, b) {
str = str.substring(a, b);
return str;
}
function maxChar() {
// 先创建一个对象
var o = {};
// 遍历字符串把不重复的字符当作对象赋值给变量
for (var i = 0; i < str.length; i++) {
var chars = str.charAt(i);
// 循环判断属性是否存在
if (o[chars]) {
o[chars]++;
} else {
o[chars] = 1;
}
}
var max = 0;
var ch = '';
// 遍历字符串,看属性值最大的字符
for (var k in o) {
if (o[k] > max) {
max = o[k];
ch = k;
}
}
return '出现次数最多的字符为:' + ch + ',次数为' + max;
}
console.log(maxChar());
console.log(getStr(0));
console.log(isExist('i'));
console.log(replaceStr('g', '22'));
console.log(subStr(1, 5));
</script>
</head>
<body>
</body>
</html>
十二、Javascript简单数据类型和复杂数据类型
1)简单类型和复杂类型
简单数据类型又叫基本数据类型或者值类型,复杂数据类型又叫做引用类型。
- 值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型
string, number, boolean, undefined, null(返回一个空对象) - 引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型
通过new关键字创建的对象(系统对象、自定义对象),如Object、Array、Date等。
2)堆和栈,以及空间分配
堆栈空间分配区别:
1、栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;
简单数据类型存放到栈里面
2、堆(操作系统):存储复杂数据类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。
复杂数据类型存放到堆里面

注意:JavaScript中没有堆栈的概念。
- 值类型(简单数据类型):string, number, boolean, undefined, null;
- 值类型变量的数据直接存放在变量(栈空间)中

- 复杂数据类型(引用类型):地址、对象
- 复杂数据类型:栈空间里存放的是地址,十六进制表示,真正的对象实例存放在堆空间中
3)简单数据类型传参
函数的形参也可以看做是一个变量,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈空间里的值复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到外部的变量。
function fn(a) {
a++;
cosole.log(a);
}
var x = 10;
fn(x);
console.log(x);

4)复杂数据类型传参
函数的形参也可以看做是一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。
function Person(name) {
this.name = name;
}
function f1(x) { // x = p
console.log(x.name); // 刘德华
x.name = '张学友';
console.log(x.name); // 张学友
}
var p = new Person('刘德华');
console.log(p.name); // 刘德华
f1(p);
console.log(p.name); // 张学友



































































































5043

被折叠的 条评论
为什么被折叠?



