JavaScript
目标:
- 掌握
JavaScript
的基础语法- 掌握
JavaScript
的常用对象(Array
、String
)- 能够根据需求灵活运用定时器,通过
JavaScript
代码进行页面跳转- 能通过
DOM
对象对标签进行常规操作- 掌握常用事件
- 能够独立完成表单校验案例
# JavaScript 简介
JavaScript 是一门跨平台、面向对象的脚本语言,而Java语言也是跨平台、面向对象的语言,只不过Java是编译语言,是需要编译成字节码文件才能运行;JavaScript是脚本语言,不需要编译,由浏览器直接解析并执行。
JavaScript是用来控制网页行为的,它能使网页可交互。接下来我们就来看下使用JavaScript可以做什么?比如:改变页面内容、修改指定元素的属性值、对表单进行校验等等,下面这些功能就是使用JavaScript来实现的:
- 改变页面内容
当点击上面左图的点击我按钮,按钮上面的文本就改为上面有图内容,这就是JS改变页面内容的功能。
- 修改指定元素的属性值
当点击上图的开灯按钮,效果就是上面右图的样子;当点击关灯按钮,效果就是上面左图的效果。其实这个功能通过img
标签展示了一张图片,通过使用JS修改img
标签的src
属性值来更换展示的图片。
- 对表单进行校验
在上面左图的输入框中输入用户名,如果输入的用户名不满足规则就展示右图(上)的效果;如果输入的用户名满足规则就展示右图(下)的效果。
JavaScript和Java是完全不同的语言,无论是概念还是设计,只是名字比较像,不过这两种语言的基础语法确有很多相似的地方,因此在学习Java后,再来学习JavaScript会相对容易些。
JavaScript(简称:JS)在 1995 年有Brendan Eich发明,并与 1997 年称为ECMA标准,ECMA规定了一套标准就叫ECMAScript,所有的客户端语言必须遵守这个标准,当然JavaScript也不例外,同样遵守了这个标准。ECMAScript 6(简称:ES6)是最新的JavaScript版本(发布于 2015 年),下面的课程就是基于最新的ES6进行讲解。
# JavaScript 引入方式
JavaScript引入方式就是HTML和JavaScript的结合方式,JavaScript引入方式有两种:
- 内部脚本:将JS代码定义在HTML页面中
- 外部脚本:将JS代码定义在外部JS文件中,然后引入到HTML页面中
# 内部脚本
在HTML中,JavaScript代码必须位于<script>
与</script>
标签之间
代码如下:
alert(数据)
是JavaScript的一个方法,作用是将参数以浏览器弹框的形式输出出来
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<script>
alert("hello js!");
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
效果如下:
从结果可以看出JS代码已经执行了。
提示
- 在HTML文档中可以在任意地方,放置任意数量的
<script></script>
标签,如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
<script>
alert("hello js1");
</script>
</head>
<body>
<script>
alert("hello js1");
</script>
</body>
</html>
<script>
alert("hello js1");
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 一般把脚本放置在
<body>
元素的底部,也就是body
关闭标签</body>
的前面,这样可以改善显示速度
因为浏览器在加载页面的时候会从上往下进行加载并解析,因此我们应该首先让用户看到页面的内容,然后再展示动态的效果。
# 外部脚本
- 第一步:定义外部JS文件,如定义一个
demo.js
的文件
目录结构如下:
demo.js
文件内容如下:
alert("hello js!");
- 第二步:在页面中引入外部的JS文件
在页面使用<script>
标签的src
属性指定JS文件的URL路径。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<script src="../js/demo.js"></script>
</body>
</html>
2
3
4
5
6
7
8
9
10
注意
- 外部脚本不能包含
<script></script>
标签:在JS文件中直接写代码即可,不需要写script
标签 <script>
标签不能自闭合:在页面中引入外部JS文件时,不能写成<script src="../js/demo.js" />
# JavaScript 基础语法
# 书写语法
区分大小写:与Java一样,变量名、函数名以及其他一切内容都是区分大小写的
每行结尾的分号可有可无,但如果在一行中写多个语句,必须加分号来区分多个语句
注释
- 单行注释:
// 注释内容
- 多行注释:
/* 注释内容 */
- 注意:JavaScript没有文档注释
- 单行注释:
大括号表示代码块,下面的语句大家肯定可以看懂
if (count == 3) { alert(count); }
1
2
3
# 输出语句
JS可以通过以下方式进行内容的输出,只不过不同的输出方式输出的位置也不同
- 使用
window.alert()
输出到警告框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<script>
window.alert("hello js!");
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
上面代码通过浏览器打开,可以看到下面的弹框效果:
- 使用
document.write()
写入页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<script>
document.write("hello js!");
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
上面代码通过浏览器打开,可以看到下面的效果:
- 使用
console.log()
写入浏览器控制台
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<script>
console.log("hello js!"); // 写入浏览器的控制台
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
上面代码通过浏览器打开,在页面上看不到任何效果,需要打开开发者工具,在浏览器控制台中可以看到如下内容:
# 变量
JavaScript中用var
关键字(variable
的缩写)来声明变量。格式为:var 变量名 = 数据值;
。JavaScript是一门弱类型语言,变量可以存放不同类型的值。比如,在定义变量时赋值为数字,还可以将变量的值改为字符串类型的数据:
var test = 20;
test = "张三";
2
JS中的变量名命名有如下规则,和Java语言基本相同
- 组成字符可以是任何字母、数字、下划线(_)或美元($)符号
- 数字不能开头
- 建议使用驼峰命名
JavaScript中var
关键字有点特殊,有以下地方和其他语言不一样
- 作用域:全局变量
{
var age = 20;
}
alert(age); // 在代码块中定义的age变量,在代码块外还可以使用
2
3
4
- 变量可以重复定义,即变量名可以重复使用
{
var age = 20;
var age = 30; // JavaScript会用30将之前的20替换掉
}
alert(age); // 浏览器弹出框中输出的结果是30
2
3
4
5
针对上面的问题,ECMAScript 6新增了let
关键字来定义局部变量。**它的用法与var
类似,但是声明的变量,只在let
关键字所在的代码块内有效,且不允许重复声明。
例如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<script>
{
let age = 20;
}
alert(age);
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
运行上面的代码,浏览器并没有弹框,说明这段代码是有问题的,通过F12
打开开发者工具可以看到如下错误信息:
ECMAScript 6新增了const
关键字,用来声明一个只读的常量,一旦声明,常量的值就不能改变。如下图:
# 数据类型
JavaScript中提供了两类数据类型:原始类型 和 引用类型。
使用
typeof
运算符可以获取变量的数据类型,比如alert(typeof age);
将以弹框的形式将age
变量的数据类型输出
原始数据类型:
- number: 数字(整数、小数、NaN(Not a Number))
var age = 20;
var price = 99.8;
alert(typeof age); // 结果是: number
alert(typeof price); // 结果是:number
2
3
4
注意
NaN
是一个特殊的number
类型的值,后面用到时再说
- string: 字符、字符串、单双引号皆可定义
var ch = "a";
var name = "张三";
var addr = "北京";
alert(typeof ch); // 结果是:string
alert(typeof name); // 结果是:string
alert(typeof addr); // 结果是:string
2
3
4
5
6
7
注意
在JS中双引号和单引号都表示字符串类型的数据
- boolean: 布尔,
true
、false
var flag = true;
var flag2 = false;
alert(typeof flag); // 结果是:boolean
alert(typeof flag2); // 结果是:boolean
2
3
4
5
- null: 对象为空
var obj = null;
alert(typeof obj); // 结果是:object
2
3
为什么打印上面的obj
变量的数据类型,结果是object
?这个官方给出了解释:
- undefined:当声明的变量未初始化时,该变量的默认值是
undefined
var a;
alert(typeof a); // 结果是:undefined
2
# 运算符
JavaScript提供了如下的运算符,大部分和Java语言都是一样的,不同的是JS关系运算符中的==
和===
:
- 一元运算符:
++
、--
- 算术运算符:
+
、-
、*
、/
、%
- 赋值运算符:
=
、+=
、-=
- 关系运算符:
>
、<
、>=
、<=
、==
、===
- 逻辑运算符:
&&
、||
、!
- 三元运算符:
条件表达式 ? true_value : false_value
==
和===
的区别:
==
:- 判断类型是否一样,如果不一样,则进行类型转换
- 类型转换后,在比较其值
===
:全等于- 判断类型是否一样,如果不一样,直接返回
false
- 如果一样,在比较其值
- 判断类型是否一样,如果不一样,直接返回
代码:
var age1 = 20;
var age2 = "20";
alert(age1 == age2); // true
alert(age1 === age2); // false
2
3
4
5
类型转换:
上述讲解==
运算符时,发现会进行类型转换,接下来我们来了解一下JavaScript中的类型转换
其他类型转为
number
string
转换为number
类型:按照字符串的字面值,转为数字,如果字面值不是数字,则转为NaN
,将string
转为number
有两种方式- 使用
+
正号运算符:
var str = +"20"; alert(str + 1); // 21
1
2- 使用
parseInt()
函数(方法),建议使用该种方法进行转换
var str = "20"; alert(parseInt(str) + 1); // 21
1
2其他类型转为
boolean
number
类型转换为boolean
类型:0
和NaN
转为false
,其他的数字转为true
string
类型转为boolean
类型:空字符串转为false
,其他字符串转为true
null
转为boolean
类型的false
undefined
转换为boolean
类型的false
代码如下:
// var flag = 3;
// var flag = "";
var flag = undefined;
if (flag) {
alert("转为true");
} else {
alert("转为false");
}
2
3
4
5
6
7
8
9
使用场景:
在Java中使用字符串前一般都会先判断字符串是否为null
,并且非空时才会做其他的一些操作,JavaScript也有类似的操作,代码如下:
var str = "abc";
// 健壮性判断
if (str != null && str.length > 0) {
alert("转为true");
} else {
alert("转为false");
}
2
3
4
5
6
7
8
但是由于JavaScript会自动进行类型转换,所以上述的判断可以进行简化,代码如下:
var str = "abc";
// 健壮性判断
if (str) {
alert("转为true");
} else {
alert("转为false");
}
2
3
4
5
6
7
8
# 流程控制语句
JavaScript中提供了和Java一样的流程控制语句,如:
if
switch
for
while
do while
if
语句
var count = 3;
if (count == 3) {
alert(count);
}
2
3
4
switch
语句
var num = 3;
switch (num) {
case 1:
alert("星期一");
break;
case 2:
alert("星期二");
break;
case 3:
alert("星期三");
break;
case 4:
alert("星期四");
break;
case 5:
alert("星期五");
break;
case 6:
alert("星期六");
break;
case 7:
alert("星期日");
break;
default:
alert("输入的星期有误");
break;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
for
循环语句
var sum = 0;
for (let i = 1; i <= 100; i++) {
// 建议for循环中使用let定义局部变量
sum += 1;
}
alert(sum);
2
3
4
5
6
while
循环语句
var sum = 0;
var i = 1;
while (i <= 100) {
sum += i;
i++;
}
alert(sum);
2
3
4
5
6
7
do while
循环语句
var sum = 0;
var i = 1;
do {
sum += i;
i++;
}
while (i < = 100);
alert(sum);
2
3
4
5
6
7
8
# 函数
函数(就是Java中的方法)是被设计为执行特定任务的代码块,JavaScript中函数是通过function
关键字来定义的。
- 定义格式
函数定义的格式有两种:
- 方式一
function 函数名(参数1, 参数2, ...) {
// 要执行的代码
}
2
3
- 方式二
var 函数名 = function(参数列表) {
// 要执行的代码
}
2
3
注意
函数中的形式参数不需要类型,原因是JavaScript是弱类型语言
function add(a, b) {
return a + b;
}
2
3
上述函数的参数a和b不需要定义数据类型,因为在每个参数前加上var
没有任何意义。
函数的返回值也不需要定义类型,在函数内部直接使用return
返回即可
- 函数调用
调用函数:函数名称(实际参数列表);
比如:
let result = add(10, 20);
注意
JS中,函数调用可以传递任意个数的参数,例如:let result = add(1, 2, 3);
它是将数据1
传递给了变量a
,将数据2
换地给了变量b
,而数据3
没有变量接收
# JavaScript 常用对象
JavaScript提供了很多对象供使用者来使用,这些对象总共分为三类:
- 基本对象
- BOM对象
- DOM对象:DOM中的对象比较多,下图只截取了一部分
接下来我们先学习基本对象,首先从Array
数组和String
字符串开始
# Array 对象
JavaScript Array
对象用于定义数组
- 定义格式
数组的定义格式有两种:
- 方式一:
var 变量名 = new Array(元素列表);
例如:
var arr = new Array(1, 2, 3); // 1, 2, 3 时候存储在数组中的数据(元素)
- 方式二
var 变量名 = [元素列表];
例如:
var arr = [1, 2, 3]; // 1, 2, 3 是存储在数组中的数据(元素)
注意
Java中的数组初始化使用的是{}
定义,而JavaScript中使用的是[]
来定义
- 元素访问
访问数组中的元素和Java语言一样,格式如下:
arr[索引] = 值;
代码演示:
// 方式一
var arr = new Array(1, 2, 3);
// alert(arr);
// 方式二
var arr2 = [1, 2, 3];
// alert(arr2);
// 访问
arr2[0] = 10;
alert(arr2);
2
3
4
5
6
7
8
9
10
11
- 特点
JavaScript中的数组相当于Java中集合,数组的长度是可以变化的,而JavaScript是弱类型,所以可以存储任意类型的数据。
例如下面的代码:
// 变长
var arr3 = [1, 2, 3];
arr3[10] = 10;
alert(arr3[10]); // 10
alert(arr3[9]); // undefined
2
3
4
5
上面代码在定义数组中给了三个元素,又给索引是10
的位置添加了数据10
,那么索引3到索引9位置的元素是什么呢?在JavaScript中没有给变量赋值的话,默认就是undefined
。
如果给arr3
数组添加字符串数据,也可以添加成功:
arr3[5] = "hello";
alert(arr3[5]); // hello
2
- 属性
Array
对象提供了很多属性,如下图就是从官方文档截取的部分属性:
我们重点讲解length
属性,该属性可以动态的获取数组的长度,有了这个属性,就可以遍历数组了
var arr = [1, 2, 3];
for (let i = 0; i < arr.length; i++) {
alert(arr[i]);
}
2
3
4
- 方法
Array
对象同样也提供了很多方法,如下图:
方法比较多,我们只演示一下push
函数和splice
函数
push
函数:给数组添加元素,也就是在数组的末尾添加元素,参数为要添加的元素
// push: 添加元素
var arr5 = [1, 2, 3];
arr5.push(10);
alert(arr5); // 数组的元素有:1, 2, 3, 10
2
3
4
splice
函数:删除元素- 参数1:索引,表示从哪个索引位置删除
- 参数2:个数,表示删除几个元素
例如:arr.splice(0, 2)
,意思就是:数组arr
从索引0开始删除,共删除2项
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
var array = ['a', 'b', 'c', 'd'];
var removeArray = array.splice(0, 2);
alert(array); // 弹出c, d
alert(removeArray); // 返回删除的项, 弹出a, b
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
splice
函数:插入功能- 参数1:插入位置
- 参数2:要删除的项数
- 参数3:插入的项
例如:arr.splice(2, 0, 4, 6)
,意思就是:数组arr
从索引2开始插入,共插入2项,即4, 6(参数0的意思就是没有要删除的项)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
var array = ['a', 'b', 'c', 'd'];
var removeArray = array.splice(1, 0, 'insert', 'update', 'delete');
alert(array); // 弹出a, insert, update, delete, b, c, d
alert(removeArray); // 弹出空
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
splice
函数:替换功能- 参数1:起始位置
- 参数2:删除的元素数
- 参数3:插入任意数量的项
例如:arr.splice(1, 1, 2, 3)
,意思就是:数组arr
从索引1开始替换,原位置元素替换为2, 3(第二个参数1的意思就是删除1项,把索引为1的项删除,替换成新元素)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
var array = ['a', 'b', 'c', 'd'];
var removeArray = array.splice(1, 1, 'insert', 'update', 'delete');
alert(array); // 弹出a, insert, update, delete, c, d
alert(removeArray); // 弹出b
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# String 对象
String
对象的创建方式有两种:
- 方式一:
var 变量名 = new String(s);
- 方式二:
var 变量名 = "字符串";
属性:
String
对象提供了很多属性,下面给大家重点介绍一下length
属性,该属性用于动态的获取字符串的长度
函数:
String
对象提供了很多函数(方法),我们经常使用的方法有两个:
String
对象还有一个函数trim()
,该方法在文档中没有体现,但所有的浏览器都支持,它可以用来去掉字符串两端的空格。
代码演示:
var str4 = ' abc ';
alert(1 + str4 + 1);
2
上面代码会输出内容1 abc 1
,很明显可以看到abc
字符串两边是有空格的,接下来用trime()
函数
var str4 = ' abc ';
alert(1 + str4.trim() + 1);
2
输出的内容是1abc1
,这就是trim()
函数的作用。
trim()
函数在后面的开发中还是比较常用的,比如登录界面:
用户在输入用户名和密码时,可能会习惯的输入一些空格,这样的话我们后端程序在判断用户名和密码的时候,肯定无法校验通过,所以我们一般会对用户输入的字符串数据进行去除左右两边的空格。
# 自定义对象
在JavaScript中自定义对象特别简单,下面就是自定义对象的格式:
var 对象名称 = {
属性名称1: 属性值1,
属性名称2: 属性值2,
...
函数名称: function(形参列表) {
},
...
};
2
3
4
5
6
7
8
9
调用属性的格式:对象名.属性名
调用函数的格式: 对象名.函数名()
接下来通过代码演示一下自定义对象的使用:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
var person = {
name: "张三",
age: 23,
eat: function() {
alert("干饭~");
}
}
alert(person.name); // 张三
alert(person.age); // 23
person.eat(); // 干饭~
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# BOM
BOM: Browser Object Model浏览器对象模型,也就是JavaScript将浏览器的各个组成部分封装为对象。
我们要操作浏览器的各个组成部分就可以通过操作BOM中的对象来实现。比如:将浏览器地址栏的地址改为https://www.itheima.com
就可以通过使用BOM中的Location
对象的href
属性,代码:location.href="https://itheima.com";
BOM中包含了如下对象:
- Window: 浏览器窗口对象
- Navigator: 浏览器对象
- Screen: 屏幕对象
- History: 历史记录对象
- Location: 地址栏对象
下图是BOM中各个对象和浏览器各个组成部分的对应关系
BOM中的Navigator
和Screen
对象基本不会使用,因此我们只讲解一下Window
、History
、Location
对象。
# Window 对象
window
对象是JavaScript对浏览器窗口进行封装的对象。
- 获取
window
对象
该对象不需要创建直接使用window
,其中window.
可以省略。比如之前使用的alert()
函数,其实就是window
对象的函数,在调用时可以写成下面两种:
- 显式使用
window
对象调用
window.alert("abc");
- 隐式调用
alert("abc");
window
对象属性
window
对象提供了用于获取其他BOM组成对象的属性
也就是说,想使用Location
对象,可以使用window
对象来获取,即window.location
,而
window.
可以省略,简化写成location
来获取Location
对象
window
对象函数
window
对象提供了很多函数供我们使用,下面列举一些常用的函数:
setTimeout(function, 毫秒值)
:在一定的时间间隔后执行一个function
,只执行一次setInterval(function, 毫秒值)
:在一定的时间间隔后执行一个function
,循环执行
代码演示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
// confirm
var flag = confirm("确认删除?");
alert(flag);
// setTimeout
setTimeout(function() {
alert("3秒后执行,只执行一次")
}, 3000);
// setInterval()
setInterval(function() {
alert("每两秒执行一次")
}, 2000)
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
而后面我们在页面删除数据时如下图每一条数据后都有删除按钮,为预防用户的一些误操作,对于删除操作需要用户进行二次确认,此时就可以用confirm()
函数。
- 案例:
- 需求:每隔一秒,灯泡切换一次状态
- 需求说明:有如下页面效果,实现定时开灯、关灯功能
- 初始页面环境
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript演示</title>
</head>
<body>
<input type="button" onclick="on()" value="开灯">
<img id="myImage" border="0" src="../imgs/off.gif" style="text-align:center;">
<input type="button" onclick="off()" value="关灯">
<script>
function on(){
document.getElementById('myImage').src='../imgs/on.gif';
}
function off(){
document.getElementById('myImage').src='../imgs/off.gif'
}
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- 完整实现代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript演示</title>
</head>
<body>
<input type="button" onclick="on()" value="开灯">
<img id="myImage" border="0" src="../imgs/off.gif" style="text-align:center;">
<input type="button" onclick="off()" value="关灯">
<script>
function on(){
document.getElementById('myImage').src='../imgs/on.gif';
}
function off(){
document.getElementById('myImage').src='../imgs/off.gif'
}
// 定义一个变量,用来记录灯的状态,偶数是开灯,奇数是关灯
var x = 0;
// 使用循环定时器
setInterval(function() {
if(x%2 == 0) {
// 表示是偶数,开灯,调用on()
on();
} else {
// 奇数,关灯,调用off()
off();
}
x++; // 改变变量的值
}, 1000);
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# History 对象
History
对象是JavaScript对历史记录进行封装的对象。
History
对象的获取
使用window.history
获取,其中window.
可以省略
History
对象的函数
这两个函数平时在访问其他的一些网站时会经常使用:
当我们点击向左的箭头,就跳转到前一个访问的页面,这就是back()
函数的作用;当点击向右的箭头,就跳转到下一个访问的页面,这就是forward()
函数的作用。
# Location 对象
Location
对象是JavaScript对地址栏封装的对象,可以通过该对象,跳转到任意页面
- 获取
Location
对象
使用window.location
获取,window.
可以省略
window.location.方法();
location.方法();
2
Location
对象属性
Location
对象提供了很多属性,常用的只有一个href
代码演示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
alert("要跳转了");
location.href = "https://www.baidu.com";
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
- 案例:3秒以后跳转到百度首页
- 分析:
- 3秒以后跳转,可以确定需要使用定时器,且只跳转一次,用
setTimeout()
- 进行页面跳转,需要用到
location
对象的href
属性
- 3秒以后跳转,可以确定需要使用定时器,且只跳转一次,用
代码实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
// alert("要跳转了");
// location.href = "https://www.baidu.com";
document.write("3秒后跳转到百度首页...");
setTimeout(function() {
location.href = "https://www.baidu.com";
}, 3000);
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# DOM
# DOM 概述
DOM: Document Object Model文档对象模型,也就是JavaScript将HTML文档的各个组成部分封装为对象。
DOM我们并不陌生,之前在学习XML就接触过,只不过文档中的标签需要我们写代码解析,而HTML文档是浏览器在解析。DOM封装的对象有:
- Document:整个文档对象
- Element:元素对象
- Attribute:属性对象
- Text:文本对象
- Comment:注释对象
如下图,左边是HTML文档内容,右边是DOM树
作用:
JavaScript通过DOM,就能够对HTML进行操作:
- 改变HTML元素的内容
- 改变HTML元素的样式(CSS)
- 对HTML DOM时间作出反应
- 添加和删除HTML元素
DOM相关概念:
DOM是W3C(万维网联盟)定义的访问HTML和XML文档的标准,该标准被分为3个不同的部分:
- 核心DOM:任何结构化文档的标准模型,XML和HTML通用的标准
- Document:整个文档对象
- Element:元素对象
- Attribute:属性对象
- Text:文本对象
- Comment:注释对象
- XML DOM:针对XML文档的标准模型
- HTML DOM:针对HTML文档的标准模型,该标准是在核心DOM基础上,对HTML中的每个标签都封装成了不同的对象
- 例如:
<img>
标签在浏览器加载到内存中时会被封装成Image
对象,同时该对象也是Element
对象 <input type='button'>
标签在加载到内存中会被封装成Button
对象,同时该对象也是Element
对象。
- 例如:
# 获取 Element 对象
HTML中的Element
对象可以通过Document
对象获取,而Document
对象是通过window
对象获取
Document
对象中提供了如下获取Element
元素对象的函数
getElementById()
:根据id
属性值获取,返回单个Element
对象getElementsByTagName()
:根据标签名获取,返回Element
对象数组getElementsByName()
:根据name
属性值获取,返回Element
对象数组getElementsByClassName()
:根据class
属性值获取,返回Element
对象数组
代码演示:下面有提前准备好的页面源码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<img id="light" src="../imgs/off.gif"> <br>
<div class="cls">传智教育</div> <br>
<div class="cls">黑马程序员</div> <br>
<input type="checkbox" name="hobby"> 电影
<input type="checkbox" name="hobby"> 旅游
<input type="checkbox" name="hobby"> 游戏
<br>
<script>
// 此处写js代码
// 1. 根据id属性值获取img元素对象,返回单个对象
var img = document.getElementById("light");
alert(img);
// 2. 根据标签名获取所有的div元素对象
// 返回一个数组,数组中存储的是div元素对象
var divs = document.getElementsByTagName("div");
// alert(divs.length); // 输出数组的长度
for (let i = 0; i < divs.length; i++) {
alert(divs[i]);
}
// 3. 获取所有满足name = 'hobby'条件的元素对象
var hobbys = document.getElementsByName("hobby");
for (let i = 0; i < hobbys.length; i++) {
alert(hobbys[i]);
}
// 4. 获取所有满足class = 'cls'条件的元素对象
var clss = document.getElementsByClassName("cls");
for (let i = 0; i < clss.length; i++) {
alert(clss[i]);
}
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# HTML Element 对象使用
HTML中的Element
元素对象有很多,不可能全部记住,以后可以根据具体的需求查阅文档来使用。
下面通过具体的案例给大家演示文档的查询和对象的使用:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<img id="light" src="../imgs/off.gif"> <br>
<div class="cls">传智教育</div> <br>
<div class="cls">黑马程序员</div> <br>
<input type="checkbox" name="hobby"> 电影
<input type="checkbox" name="hobby"> 旅游
<input type="checkbox" name="hobby"> 游戏
<br>
<script>
// 此处写js代码
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
需求:
- 点亮灯泡:此案例需要改变
img
标签的图片,我们需要查询文档,下图是查看文档的流程
代码实现:
// 1. 根据id = 'light'获取img元素对象
var img = document.getElementById("light");
// 2. 修改img对象的src属性来改变图片
img.src = "../imgs/on.gif";
2
3
4
- 将所有的
div
标签的标签体内容替换为呵呵
// 1. 获取所有的div元素对象
var divs = document.getElementsByTagName("div");
/*
style: 设置元素css样式
innerHTML: 设置元素内容
*/
// 2. 遍历数组,获取到每一个div元素对象,并修改元素内容
for (let i = 0; i < divs.length; i++) {
// divs[i].style.color = 'red';
divs[i].innerHTML = "呵呵";
}
2
3
4
5
6
7
8
9
10
11
- 使所有的复选框呈现被选中状态:此需求我们需要看复选框元素对象中有哪些属性或者函数来操作复选框的选中状态。
// 1. 获取所有的复选框对象
var hobbys = document.getElementsByName("hobby");
// 2. 遍历数组,将复选框元素对象的checked属性值设置为true来改变选中状态
for (let i = 0; i < hobbys.length; i++) {
hobbys[i].checked = true;
}
2
3
4
5
6
# 事件监听
在学习事件监听之前,我们需要先了解一下什么是事件?
HTML事件是发生在HTML元素上的事情。比如:页面上的按钮被点击、鼠标移动到元素之上、按下键盘按键等都是事件。
事件监听是JavaScript可以在事件被侦测到时执行一段逻辑代码。例如下图当中我们点击开灯、关灯按钮,就需要通过JS代码替换图片。
在比如下图输入框,当我们输入了用户名,当光标离开输入框,就需要通过JS代码对输入的内容进行校验,没通过校验就需要提示用户名格式有误!。
# 事件绑定
JavaScript提供了两种时间绑定方式:
- 方式一:通过HTML标签中的事件属性进行绑定,如下代码,有一个按钮元素,在改标签上定义事件属性,在事件属性中绑定函数。
onclick
就是单击事件的事件属性,onclick='on()'
表示点击事件绑定了一个名为on()
的函数
<input type="button" onclick='on()'>
下面是点击事件绑定的on()
函数
function on() {
alert("我被点了");
}
2
3
- 方式二:通过DOM元素属性绑定,如下代码是按钮标签,在该标签上我们并没有使用事件属性,绑定事件的操作需要在JS代码中实现
<input type="button" id="btn">
下面JS代码是获取了id='btn'
的元素对象,然后将onclick
作为该对象的属性,并且绑定了匿名函数,该函数是在事件触发后自动执行
document.getElementById("btn").onclick = function() {
alert("我被点了");
}
2
3
代码演示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--方式1:在下面input标签上添加 onclick 属性,并绑定 on() 函数-->
<input type="button" value="点我" onclick="on()"> <br>
<input type="button" value="再点我" id="btn">
<script>
function on(){
alert("我被点了");
}
//方式2:获取 id="btn" 元素对象,通过调用 onclick 属性 绑定点击事件
document.getElementById("btn").onclick = function (){
alert("我被点了");
}
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 常见事件
上面案例中使用了onclick
事件属性,那么都有哪些事件属性呢?下面就来列举一下常见的事件属性:
事件属性 | 说明 |
---|---|
onclick | 鼠标单击事件 |
onblur | 元素失去焦点事件 |
onfocus | 元素获得焦点事件 |
onload | 某个页面或图像被完成加载 |
onsubmit | 当表单提交时触发该事件 |
onmouseover | 鼠标被移到某元素之上 |
onmouseout | 鼠标从某元素移开 |
onfocus
获得焦点事件:如图,当点击了输入框后,输入框就获得了焦点,下图所展示的是当获取焦点后会更改输入框的背景颜色
onblur
失去焦点事件:如图,当点击输入框后,输入框就获得了焦点,再点击页面其他位置,那输入框就失去了焦点,图中示例为当失去焦点时将文本转换为大写:
onmouseout
:鼠标移出事件onmouseover
:鼠标移入事件
如图,当鼠标移入到苹果图片上时,苹果图片变大;当鼠标移出苹果图片时,苹果图片变小
onsubmit
:表单提交事件,如下是带有表单的页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form id="register" action="#" >
<input type="text" name="username" />
<input type="submit" value="提交">
</form>
<script>
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
上面代码的表单,当我们点击提交按钮后,表单就会提交,此处默认使用的是GET
提交方式,会将提交的数据拼接到URL
后,现在需要通过JS代码实现阻止表单提交的功能,JS代码实现如下:
- 获取
form
表单元素对象 - 给
form
表单元素对象绑定onsubmit
事件,并绑定匿名函数 - 该匿名函数如果返回
true
,提交表单;如果返回false
,阻止表单提交
document.getElementById("register").onsubmit = function() {
// onsubmit返回true,则表单会被提交,返回false,表单不提交
return true;
}
2
3
4
# 表单验证案例
# 需求
如上图注册页面,如果输入的用户名、密码、手机号符合规则,则允许提交,否则不允许提交
- 当输入框失去焦点时,验证输入内容是否符合要去
- 当点击注册按钮时,判断所有输入框的内容是否都符合要求,如果不符合则阻止表单提交
# 环境准备
下面是初始页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>欢迎注册</title>
<link href="../css/register.css" rel="stylesheet">
</head>
<body>
<div class="form-div">
<div class="reg-content">
<h1>欢迎注册</h1>
<span>已有帐号?</span> <a href="#">登录</a>
</div>
<form id="reg-form" action="#" method="get">
<table>
<tr>
<td>用户名</td>
<td class="inputs">
<input name="username" type="text" id="username">
<br>
<span id="username_err" class="err_msg" style="display: none">用户名不太受欢迎</span>
</td>
</tr>
<tr>
<td>密码</td>
<td class="inputs">
<input name="password" type="password" id="password">
<br>
<span id="password_err" class="err_msg" style="display: none">密码格式有误</span>
</td>
</tr>
<tr>
<td>手机号</td>
<td class="inputs"><input name="tel" type="text" id="tel">
<br>
<span id="tel_err" class="err_msg" style="display: none">手机号格式有误</span>
</td>
</tr>
</table>
<div class="buttons">
<input value="注 册" type="submit" id="reg_btn">
</div>
<br class="clear">
</form>
</div>
<script>
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# 输入框验证
- 校验用户名:当用户名输入框失去焦点时,判断输入的内容是否符合长度是6-12位规则,不符合使
id='username_err'
的span
标签显示出来 - 校验密码:当密码输入框失去焦点时,判断输入的内容是否符合长度是6-12位规则,不符合使
id='password_err'
的span
标签显示出来 - 校验手机号:当手机号输入框失去焦点的时候,判断输入的内容是否符合长度是11位规则,不符合使
id='tel_err'
的span
标签显示出来
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>欢迎注册</title>
<link href="../css/register.css" rel="stylesheet">
</head>
<body>
<div class="form-div">
<div class="reg-content">
<h1>欢迎注册</h1>
<span>已有帐号?</span> <a href="#">登录</a>
</div>
<form id="reg-form" action="#" method="get">
<table>
<tr>
<td>用户名</td>
<td class="inputs">
<input name="username" type="text" id="username">
<br>
<span id="username_err" class="err_msg" style="display: none">用户名不太受欢迎</span>
</td>
</tr>
<tr>
<td>密码</td>
<td class="inputs">
<input name="password" type="password" id="password">
<br>
<span id="password_err" class="err_msg" style="display: none">密码格式有误</span>
</td>
</tr>
<tr>
<td>手机号</td>
<td class="inputs"><input name="tel" type="text" id="tel">
<br>
<span id="tel_err" class="err_msg" style="display: none">手机号格式有误</span>
</td>
</tr>
</table>
<div class="buttons">
<input value="注 册" type="submit" id="reg_btn">
</div>
<br class="clear">
</form>
</div>
<script>
// 1. 验证用户名是否符合规则
// 1.1 获取用户名的输入框
var usernameInput = document.getElementById("username");
// 1.2 绑定onblur事件,失去焦点
usernameInput.onblur = function() {
// 1.3 获取用户输入的用户名
var username = usernameInput.value.trim();
// 1.4 判断用户名是否符合规则:长度6~12
if (username.length >= 6 && username.length <= 12) {
// 符合规则
document.getElementById("username_err").style.display = 'none';
} else {
// 不符合规则
document.getElementById("username_err").style.display = '';
}
}
// 2. 验证密码是否符合规则
// 2.1 获取密码输入框
var passwordInput = document.getElementById("password");
// 2.2 绑定onblur事件
passwordInput.onblur = function() {
// 2.3 获取用户输入的密码
var password = passwordInput.value.trim();
// 2.4 判断密码是否符合规则:长度6~12
if (password.length >= 6 && password <= 12) {
// 符合规则
document.getElementById("password_err").style.display = 'none';
} else {
document.getElementById("password_err").style.display = '';
}
}
// 3. 验证手机号是否符合规则
// 3.1 获取手机号输入框
var telInput = document.getElementById("tel");
// 3.2 绑定onblur事件
telInput.onblur = function() {
// 3.3 获取输入的手机号
var tel = telInput.value.trim();
// 3.4 判断手机号是否符合规则:11位
if (tel.length == 11) {
// 符合规则
document.getElementById("tel_err").style.display = 'none';
} else {
document.getElementById("tel_err").style.display = '';
}
}
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# 表单验证
当用户点击注册按钮时,需要同时对输入的用户名、密码、手机号校验,如果都符合规则,则提交表单,如果有任意一个不符合规则,则不允许提交表单。实现该功能需要获取表单元素对象,并绑定onsubmit
事件
// 1. 获取表单对象
var regForm = document.getElementById("reg-form");
// 2. 绑定onsubmit事件
regForm.onsubmit = function() {
}
2
3
4
5
6
7
onsubmit
事件绑定的函数需要对输入的用户名、密码、手机号进行校验,这些校验我们之前都已经实现了,那么注册这里还需要进行再次校验吗?显然不需要,但是需要对之前校验的代码进行改造,把每个校验的代码专门抽象到有名字的函数中,方便调用,并且每个函数都要返回结果用来决定是提交表单还是阻止表单提交,代码如下:
//1. 验证用户名是否符合规则
//1.1 获取用户名的输入框
var usernameInput = document.getElementById("username");
//1.2 绑定onblur事件 失去焦点
usernameInput.onblur = checkUsername;
function checkUsername() {
//1.3 获取用户输入的用户名
var username = usernameInput.value.trim();
//1.4 判断用户名是否符合规则:长度 6~12
var flag = username.length >= 6 && username.length <= 12;
if (flag) {
//符合规则
document.getElementById("username_err").style.display = 'none';
} else {
//不合符规则
document.getElementById("username_err").style.display = '';
}
return flag;
}
//1. 验证密码是否符合规则
//1.1 获取密码的输入框
var passwordInput = document.getElementById("password");
//1.2 绑定onblur事件 失去焦点
passwordInput.onblur = checkPassword;
function checkPassword() {
//1.3 获取用户输入的密码
var password = passwordInput.value.trim();
//1.4 判断密码是否符合规则:长度 6~12
var flag = password.length >= 6 && password.length <= 12;
if (flag) {
//符合规则
document.getElementById("password_err").style.display = 'none';
} else {
//不合符规则
document.getElementById("password_err").style.display = '';
}
return flag;
}
//1. 验证手机号是否符合规则
//1.1 获取手机号的输入框
var telInput = document.getElementById("tel");
//1.2 绑定onblur事件 失去焦点
telInput.onblur = checkTel;
function checkTel() {
//1.3 获取用户输入的手机号
var tel = telInput.value.trim();
//1.4 判断手机号是否符合规则:长度 11
var flag = tel.length == 11;
if (flag) {
//符合规则
document.getElementById("tel_err").style.display = 'none';
} else {
//不合符规则
document.getElementById("tel_err").style.display = '';
}
return flag;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
而onsubmit
绑定的函数需要调用checkUsername()
函数、checkPassword()
函数、checkTel()
函数
// 1. 获取表单对象
var regForm = document.getElementById("reg-form");
// 2. 绑定onsubmit事件
regForm.onsubmit = function() {
// 逐个判断每一个表单向是否都符合规则,如果有一个不符合就返回false
var flag = checkUsername() && checkPassword() && checkTel();
return flag;
}
2
3
4
5
6
7
8
9
10
# RegExp 对象
RegExp
是正则对象,正则对象是判断指定字符串是否符合规则。如下图百度贴吧中的帖子:
现在可以通过爬虫技术去爬取该页面的源代码,然后获取页面中所有的邮箱,后面就可以给这些邮箱地址发送推广的邮件。那么随之而来就有一个问题,我们如何来确定一个字符串是否为邮箱?可以通过使用正则表达式来匹配邮箱。
在JS中对正则表达式封装的对象就是正则对象。
# 正则对象使用
- 创建对象
- 正则对象有两种创建方式:
- 直接量方式:注意不要加引号,
var reg = /正则表达式/;
- 创建
RegExp
对象:var reg = new RegExp("正则表达式");
- 直接量方式:注意不要加引号,
- 函数
test(str)
:判断指定字符串是否符合规则,返回true
或false
# 正则表达式
从上面创建正则对象的格式可以看出不管哪种方式都需要正则表达式,那么正则表达式是什么?
正则表达式定义了字符串的组成规则,也就是判断指定的字符串是否符合指定的规则,如果符合则返回true
,否则返回false
正则表达式是和语言无关的,很多语言都支持正则表达式,Java语言也支持,只不过正则表达式在不同的语言中使用的方式有所不同,JS中需要使用正则对象来使用正则表达式。
正则表达式常用的规则如下:
^
:表示开始$
:表示结束[]
:代表某个范围内的单个字符,比如:[0-9]
单个数字字符.
:代表任意单个字符,除了换行和行结束符\w
:代表单词字符:字母、数字、下划线,相当于[A-Za-z0-9]
\d
:代表数字字符:相当于[0-9]
量词:
+
:至少一个*
:零个或多个?
:零个或一个{x}
:x个{m,}
:至少m个{m,n}
:至少m个,至多n个
代码演示:
// 规则:单词字符,6~12
// 1. 创建正则对象,对正则表达式进行封装
var reg = /^\w{6,12}$/;
var str = "abcccc";
// 2. 判断str字符串是否符合reg封装的正则表达式规则
var flag = reg.test(str);
alert(flag);
2
3
4
5
6
7
8
# 表单校验案例改进
表单校验案例中的规则是我们进行一系列的判断来实现的,现在学习了正则对象后,接下来我们就可以使用正则对象来改进这个案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>欢迎注册</title>
<link href="../css/register.css" rel="stylesheet">
</head>
<body>
<div class="form-div">
<div class="reg-content">
<h1>欢迎注册</h1>
<span>已有帐号?</span> <a href="#">登录</a>
</div>
<form id="reg-form" action="#" method="get">
<table>
<tr>
<td>用户名</td>
<td class="inputs">
<input name="username" type="text" id="username">
<br>
<span id="username_err" class="err_msg" style="display: none">用户名不太受欢迎</span>
</td>
</tr>
<tr>
<td>密码</td>
<td class="inputs">
<input name="password" type="password" id="password">
<br>
<span id="password_err" class="err_msg" style="display: none">密码格式有误</span>
</td>
</tr>
<tr>
<td>手机号</td>
<td class="inputs"><input name="tel" type="text" id="tel">
<br>
<span id="tel_err" class="err_msg" style="display: none">手机号格式有误</span>
</td>
</tr>
</table>
<div class="buttons">
<input value="注 册" type="submit" id="reg_btn">
</div>
<br class="clear">
</form>
</div>
<script>
// 1. 验证用户名是否符合规则
// 1.1 获取用户名的输入框
var usernameInput = document.getElementById("username");
// 1.2 绑定onblur事件,失去焦点
usernameInput.onblur = function() {
// 1.3 获取用户输入的用户名
var username = usernameInput.value.trim();
// 1.4 判断用户名是否符合规则:长度6~12
var reg = /^\w{6,12}$/;
var flag = reg.test(username);
if (flag) {
// 符合规则
document.getElementById("username_err").style.display = 'none';
} else {
// 不符合规则
document.getElementById("username_err").style.display = '';
}
}
// 2. 验证密码是否符合规则
// 2.1 获取密码输入框
var passwordInput = document.getElementById("password");
// 2.2 绑定onblur事件
passwordInput.onblur = function() {
// 2.3 获取用户输入的密码
var password = passwordInput.value.trim();
var reg = /^\w{6,12}$/;
var flag = reg.test(password);
// 2.4 判断密码是否符合规则:长度6~12
if (flag) {
// 符合规则
document.getElementById("password_err").style.display = 'none';
} else {
document.getElementById("password_err").style.display = '';
}
}
// 3. 验证手机号是否符合规则
// 3.1 获取手机号输入框
var telInput = document.getElementById("tel");
// 3.2 绑定onblur事件
telInput.onblur = function() {
// 3.3 获取输入的手机号
var tel = telInput.value.trim();
var reg = /^[1]\d{10}$/;
var flag = reg.test(tel);
// 3.4 判断手机号是否符合规则:11位
if (flag) {
// 符合规则
document.getElementById("tel_err").style.display = 'none';
} else {
document.getElementById("tel_err").style.display = '';
}
}
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105