0
点赞
收藏
分享

微信扫一扫

javascript学习笔记

倚然君 2022-03-14 阅读 120
javascript

【前端总路线学习笔记】

文章目录

javascript

一、简介

1.什么是语言

计算机就是一个由人来控制的机器,人让它干嘛,它就得干嘛。

我们要学习的语言就是人和计算机交流的工具,人类通过语言来控制、操作计算机。

编程语言和我们说的中文、英文本质上没有区别,只是语法比较特殊。

语言的发展:

  • 纸带机:机器语言

  • 汇编语言:符号语言

  • 现代语言:高级语言

2.起源

JavaScript诞生于1995年,它的出现主要是用于处理网页中的前端验证。

所谓的前端验证,就是指检查用户输入的内容是否符合一定的规则。

​ 比如:用户名的长度,密码的长度,邮箱的格式等。

3.简史

JavaScript是由网景公司发明,起初命名为LiveScript,后来由于SUN公司的介入更名为了JavaScript。

1996年微软公司在其最新的IE3浏览器中引入了自己对JavaScript的实现JScript。

于是在市面上存在两个版本的JavaScript,一个网景公司的JavaScript和微软的JScript

为了确保不同的浏览器上运行的JavaScript标准一致,所以几个公司共同定制了JS的标准名命名为ECMAScript

4.ECMAScript实现

ECMAScript是一个标准,而这个标准需要由各个厂商去实现。

不同的浏览器厂商对该标准会有不同的实现

image-20220221152044990

我们已经知道ECMAScriptJavaScript标准,所以一般情况下这两个词我们认为是一个意思。

但是实际上JavaScript的含义却要更大一些。

一个完整的JavaScript实现应该由以下三个部分构成:

image-20220221152305256

5.JS的特点

  1. 解释型语言
    • JavaScript是一门解释型语言,所谓解释型值语言不需要被编译为机器码在执行,而是直接执行。
    • 由于少了编译这一步骤,所以解释型语言开发起来尤为轻松,但是解释型语言运行较慢也是它的劣势。
    • 不过解释型语言中使用了JIT技术,使得运行速度得以改善。
  2. 类似于 C 和 Java 的语法结构
    • JavaScript的语法结构与C和Java很像,向for、if、while等语句和Java的基本上是一模一样的。
    • 所以有过C和Java基础的同学学习起来会轻松很多。
    • 不过JavaScript和与Java的关系也仅仅是看起来像而已。
  3. 动态语言
    • JavaScript是一门动态语言,所谓的动态语言可以暂时理解为在语言中的一切内容都是不确定的。比如一个变量,这一时刻是个整型,下一时刻可能会变成字符串了。
    • 不过在补充一句动态语言相比静态语言性能上要差一些,不过由于JavaScript中应用的JIT技术,所以JS可能是运行速度最快的动态语言了
  4. 基于原型的面向对象
    • JavaScript是一门面向对象的语言。
    • Java也是一门面向对象的语言,但是与Java不同JavaScript是基于原型的面向对象。

二、基础语法

1. Helloword-编写位置-基本语法-字面量和变量-标识符

prompt() 输入语法

	- JavaScript负责页面中的的行为。
	- 它是一门运行在浏览器端的脚本语言。
	- JS的编写的位置
		1.可以编写到标签的指定属性中
			<button οnclick="alert('hello');">我是按钮</button>
			<a href="javascript:alert('aaa');">超链接</a>
			虽然可以写在标签的属性中,但是他们属于结构与行为耦合,不方便维护,不推荐使用
			
		2.可以编写到script标签中   *****
			<script type="text/javascript">
				//编写js代码
			</script>
			
			type:默认值text/javascript可以不写,不写也是这个值。
			
		3.可以将代码编写到外部的js文件中,然后通过标签将其引入 *****
			<script type="text/javascript" src="文件路径"></script>
			src:当需要引入一个外部的js文件时,使用该属性指向文件的地址
			写到外部文件中可以在不同的页面中同时引用,也可以利用到浏览器的缓存机制
			script标签一旦用于引入外部文件了,就不能在编写代码了,即使编写了浏览器也会忽略
			如果需要则可以在创建一个新的script标签用于编写内部代码
			
	- 输出语句
		- alert("要输出的内容");
			- 该语句会在浏览器窗口中弹出一个警告框
			
		- document.write("要输出的内容");
			- 该内容将会被写到body标签中,并在页面中显示
			
		- console.log("要输出的内容");
			- 该内容会被写到开发者工具的控制台中
			
	- 基本的语法
		- 注释
			- 单行注释
				//注释内容
			- 多行注释
				/*
					注释内容
				*/
				
		- JS严格区分大小写	
		- JS中每条语句以分号(;)结尾
		- JS中会自动忽略多个空格和换行,所以我们可以利用空格和换行对代码进行格式化。
		
	- 字面量和变量
		- 字面量
			- 字面量实际上就是一些固定的值,比如 1 2 3 4 true false null NaN "hello"
				字面量都是不可以改变的。
			- 由于字面量不是很方便使用,所以在JS中很少直接使用字面量
		
		- 变量
			- 变量可以用来保存字面量,并且可以保存任意的字面量
			- 一般都是通过变量来使用字面量,而不直接使用字面量,而且也可以通过变量来对字面量进行一个描述
			- 声明变量
				- 使用var关键字来声明一个变量
				var a;
				var b;
				var c;
				
			- 为变量赋值
				a = 1;
				b = 2;
				c = 3;
				
			- 声明和赋值同时进行 *****
				var d = 456;
				var e = 789;
				
	- 标识符
		- 在JS中所有的可以自主命名的内容,都可以认为是一个标识符,
			是标识符就应该遵守标识符的规范。
		- 比如:变量名、函数名、属性名
		- 规范:
			1.标识符中可以含有字母、数字、_、$
			2.标识符不能以数字开头
			3.标识符不能是JS中的关键字和保留字
			4.标识符一般采用驼峰命名法
				xxxYyyZzz helloWorld
		- JS底层保存标识符时实际上是采用的Unicode编码,	
			所以理论上讲,所有的utf-8中含有的内容都可以作为标识符
			

关键字

image-20220221161804995

保留字符

image-20220221161822014

其他不建议使用的标识符

image-20220221161854502

2.数据类型-基本数据类型(String-Number-Boolean-Null-Undefined)-类型转换

1.数据类型
	- JS中一共分成六种数据类型
		- String 字符串
		- Number 数值
		- Boolean 布尔值
		- Null 空值
		- Undefined 未定义
		- Object 对象
	- 其中基本数据类型有	
		- String 字符串
			- JS中的字符串需要使用引号引起来双引号或单引号都行
			- 在字符串中使用\作为转义字符
				\'  ==> '
				\"  ==> "
				\n  ==> 换行
				\t  ==> 制表符
				\\  ==> \	
				\b ==> 空格
				\r ==> 回车
				
			- 使用typeof运算符检查字符串时,会返回"string"	
				var a = 'a'
				console.log(typeof a)
			
		- Number 数值
			- JS中所有的整数和浮点数都是Number类型
			- 特殊的数字
				Infinity 正无穷
				-Infinity 负无穷
				NaN 非法数字(Not A Number)
					NaN 是一个特殊的数字,表示Not A Number
					使用typeof检查一个NaN也会返回number
			- 其他进制的数字的表示:
				0b 开头表示二进制,但是不是所有的浏览器都支持
				0 开头表示八进制
				0x 开头表示十六进制
				
			- 使用typeof检查一个Number类型的数据时,会返回"number"
				(包括NaN 和 Infinity)
			- JS中可以表示的数字的最大值 Number.MAX_VALUE  1.7976931348623157e+308
				Number.MIN_VALUE 大于0的最小值 5e-324
			
			- 如果使用JS进行浮点运算,可能得到一个不精确的结果
				所以千万不要使用JS进行对精确度要求比较高的运算	
			
		- Boolean 布尔值
			- 布尔值主要用来进行逻辑判断,布尔值只有两个
			- true 逻辑的真
			- false 逻辑的假
			- 使用typeof检查一个布尔值时,会返回"boolean"	
		
		- Null 空值
			- 空值专门用来表示为空的对象,Null类型的值只有一个
			- null
			- 使用typeof检查一个Null类型的值时会返回"object"

		- Undefined 未定义
			- 如果声明一个变量但是没有为变量赋值此时变量的值就是undefined
			- 该类型的值只有一个 undefined
			- 使用typeof检查一个Undefined类型的值时,会返回"undefined"

	- 引用数据类型	
		- Object 对象
		
	- 类型转换
		- 类型转换就是指将其他的数据类型,转换为String Number 或 Boolean
		- 转换为String
			- 方式一(强制类型转换):
				- 调用被转换数据的toString()方法
				- 例子:
					var a = 123;
					a = a.toString();
				- 注意:这个方法不适用于null和undefined
					由于这两个类型的数据中没有方法,所以调用toString()时会报错
					
			- 方式二(强制类型转换):
				- 调用String()函数
				- 例子:
					var a = 123;
					a = String(a);
				- 原理:对于Number Boolean String都会调用他们的toString()方法来将其转换为字符串,
					对于null值,直接转换为字符串"null"。对于undefined直接转换为字符串"undefined"
					
			- 方式三(隐式的类型转换): *****
				- 为任意的数据类型 +""
				- 例子:
					var a = true;
					a = a + "";
				- 原理:和String()函数一样	
				
		- 转换为Number
			- 方式一(强制类型转换):
				- 调用Number()函数
				- 例子:
					var s = "123";
					s = Number(s);
				- 转换的情况:
					1.字符串 --> 数字
						- 如果字符串是一个合法的数字,则直接转换为对应的数字
						- 如果字符串是一个非法的数字,则转换为NaN
						- 如果是一个空串或纯空格的字符串,则转换为0
					2.布尔值 --> 数字
						- true转换为1
						- false转换为0
					3.空值 --> 数字
						- null转换为0
					4.未定义 --> 数字
						- undefined 转换为NaN
						
			- 方式二(强制类型转换):
				- 调用parseInt()或parseFloat()
				- 这两个函数专门用来将一个*字符串*转换为数字的
				- parseInt()
					- 可以将一个字符串中的有效的整数位提取出来,并转换为Number
					- 例子:
						var a = "123.456px";
						a = parseInt(a); //123
					- 如果需要可以在parseInt()中指定一个第二个参数,来指定进制	
							a = "070";
							//可以在parseInt()中传递一个第二个参数,来指定数字的进制
							a = parseInt(a,10);
				- parseFloat()
					- 可以将一个字符串中的有效的小数位提取出来,并转换为Number
					- 例子:
						var a = "123.456px";
						a = parseFloat(a); //123.456
				- 如果对非String使用parseInt()或parseFloat()
					它会先将其转换为String然后在操作
						
			- 方式三(隐式的类型转换):
				- 使用一元的+来进行隐式的类型转换
				-  * / - 隐式转换
				- 例子:
					var a = "123";
					a = +a;
					
				- 原理:和Number()函数一样	
				
		- 转换为布尔值
			- 方式一(强制类型转换):
				- 使用Boolean()函数
				- 例子:
					var s = "false";
					s = Boolean(s); //true
				- 转换的情况
					字符串 --> 布尔
						- 除了空串其余全是true
						
					数值 --> 布尔
						- 除了0和NaN其余的全是true
						
					null、undefined ---> 布尔
						- 都是false
						
					对象 ---> 布尔
						- 都是true
			
			- 方式二(隐式类型转换):	
				- 为任意的数据类型做两次非运算,即可将其转换为布尔值
				- 例子:	
					var a = "hello";
					a = !!a; //true
		

3.运算符(算数运算符-一元运算符-逻辑运算符-赋值运算符-关系运算符-相等运算符-三元运算符)

1.运算符

	- 运算符
		- 运算符也称为操作符
		- 通过运算符可以对一个或多个值进行运算或操作
		- typeof运算符
			- 用来检查一个变量的数据类型
			- 语法:typeof 变量
			- 它会返回一个用于描述类型的字符串作为结果
			
		- 算数运算符
			+	对两个值进行加法运算并返回结果
			-  	对两个值进行减法运算并返回结果
			*	对两个值进行乘法运算并返回结果
			/	对两个值进行除法运算并返回结果
			%	对两个值进行取余运算并返回结果
			**  次方
			
			- 除了加法以外,对非Number类型的值进行运算时,都会先转换为Number然后在做运算。
			- 而做加法运算时,如果是两个字符串进行相加,则会做拼串操作,将两个字符连接为一个字符串。
			- 任何值和字符串做加法,都会先转换为字符串,然后再拼串

		- 一元运算符
			- 一元运算符只需要一个操作数
			- 一元的+
				- 就是正号,不会对值产生任何影响,但是可以将一个非数字转换为数字
				- 例子:
					var a = true;
					a = +a;
					对于非Number类型的值,
					它会将先转换为Number,然后在运算
					可以对一个其他的数据类型使用+,来将其转换为number
					它的原理和Number()函数一样
				
			- 一元的-
				- 就是负号,可以对一个数字进行符号位取反
				- 例子:
					var a = 10;
					a = -a;
					
			- 自增
				- 自增可以使变量在原值的基础上自增1
				- 自增使用 ++
				- 自增可以使用 前++(++a)后++(a++)
				- 无论是++a 还是 a++都会立即使原变量自增1
					不同的是++a和a++的值是不同的,
						++a的值是变量的新值(自增后的值)
						a++的值是变量的原值(自增前的值)

			- 自减	
				- 自减可以使变量在原值的基础上自减1
				- 自减使用 --
				- 自减可以使用 前--(--a)后--(a--)
				- 无论是--a 还是 a--都会立即使原变量自减1
					不同的是--a和a--的值是不同的,
						--a的值是变量的新值(自减后的值)
						a--的值是变量的原值(自减前的值)
						
						
						
	- 逻辑运算符
		!
			- 非运算可以对一个布尔值进行取反,true变false false边true
			- 当对非布尔值使用!时,会先将其转换为布尔值然后再取反
			- 我们可以利用!来将其他的数据类型转换为布尔值
		
		&&
			- &&可以对符号两侧的值进行与运算
			- 只有两端的值都为true时,才会返回true。只要有一个false就会返回false。
			- 与是一个短路的与,如果第一个值是false,则不再检查第二个值
			- 对于非布尔值,它会将其转换为布尔值然后做运算,并返回原值
			- 规则:
					1.如果第一个值为false,则返回第一个值
					2.如果第一个值为true,则返回第二个值
				****3.返回的不一定是布尔值,而是返回表达式结果
		
		||
			- ||可以对符号两侧的值进行或运算
			- 只有两端都是false时,才会返回false。只要有一个true,就会返回true。
			- 或是一个短路的或,如果第一个值是true,则不再检查第二个值
			- 对于非布尔值,它会将其转换为布尔值然后做运算,并返回原值
			- 规则:	
					1.如果第一个值为true,则返回第一个值
					2.如果第一个值为false,则返回第二个值
					
		 && || 非布尔值的情况
			 * 	- 与运算:
			 * 		- 如果第一个值为true,则必然返回第二个值
			 * 		- 如果第一个值为false,则直接返回第一个值 
			 * 	- 或运算
			 * 		- 如果第一个值为true,则直接返回第一个值
			 * 		- 如果第一个值为false,则返回第二个值
				
	- 赋值运算符
		= 
			- 可以将符号右侧的值赋值给左侧变量
			
		+=
			- a += 5 相当于 a = a+5
			- var str = "hello";  str += "world";
			
		-=
			- a -= 5  相当于 a = a-5
			
		*=
			- a *= 5 相当于 a = a*5
			
		/=
			- a /= 5 相当于 a = a/5	
	
		%=
			- a %= 5 相当于 a = a%5	
			
			
	- 关系运算符
		- 关系运算符用来比较两个值之间的大小关系的
			>
			>=
			<
			<=
		- 关系运算符的规则和数学中一致,用来比较两个值之间的关系,
			如果关系成立则返回true,关系不成立则返回false。
		- 如果比较的两个值是非数值,会将其转换为Number然后再比较。 
			任何值和NaN做任何比较都是false
		- 如果比较的两个值都是字符串,此时会比较字符串的Unicode编码,而不会转换为Number。
			比较字符编码时是一位一位进行比较
			如果两位一样,则比较下一位,所以借用它来对英文进行排序
			比较中文时没有意义
			
			如果比较的两个字符串型的数字,可能会得到不可预期的结果
	********注意:在比较两个字符串型的数字时,一定一定一定要转型
			
	- 相等运算符
		==
			- 相等,判断左右两个值是否相等,如果相等返回true,如果不等返回false
			- 相等会自动对两个值进行类型转换,如果对不同的类型进行比较,会将其转换为相同的类型然后再比较,
				转换后相等它也会返回true
		!=
			- 不等,判断左右两个值是否不等,如果不等则返回true,如果相等则返回false
			- 不等也会做自动的类型转换。
			
		===
			- 全等,判断左右两个值是否全等,它和相等类似,只不过它不会进行自动的类型转换,
				如果两个值的类型不同,则直接返回false
				
		!==
			- 不全等,和不等类似,但是它不会进行自动的类型转换,如果两个值的类型不同,它会直接返回true
			
		特殊的值:
			- null和undefined
				- 由于undefined衍生自null,所以null == undefined 会返回true。
					但是 null === undefined 会返回false。
					
					0 != null    0!= undefined
				
					
			- NaN
				- NaN不与任何值相等,报告它自身 NaN == NaN //false
				
			- 判断一个值是否是NaN
				- 使用isNaN()函数
				
	- 三元运算符:
		?:
			- 语法:条件表达式?语句1:语句2;
			- 执行流程:
				先对条件表达式求值判断,
					如果判断结果为true,则执行语句1,并返回执行结果
					如果判断结果为false,则执行语句2,并返回执行结果
					
	- 优先级:
		- 和数学中一样,JS中的运算符也是具有优先级的,
			比如 先乘除 后加减 先与 后或
		- 具体的优先级可以参考优先级的表格,在表格中越靠上的优先级越高,
			优先级越高的越优先计算,优先级相同的,从左往右计算。
		- 优先级不需要记忆,如果越到拿不准的,使用()来改变优先级。

image-20220221205635215

4.html页面和 js使用 Unicode编码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<script type="text/javascript">
			
			/*
			 * 在字符串中使用转义字符输入Unicode编码
			 * 	\u四位编码
			 */
			console.log("\u2620");
			
		</script>
	</head>
	<body>
		
		<!--在网页中使用Unicode编码
			&#编码; 这里的编码需要的是10进制
		-->
		<h1 style="font-size: 200px;">&#9760;</h1>
		<h1 style="font-size: 200px;">&#9856;</h1>
		
	</body>
</html>

5.语句 代码块

语句
	前边我所说表达式和运算符等内容可以理解成是我们一门语言中的单词,短语。
	而语句(statement)就是我们这个语言中一句一句完整的话了。
	语句是一个程序的基本单位,JS的程序就是由一条一条语句构成的,每一条语句使用;结尾。
	JS中的语句默认是由上至下顺序执行的,但是我们也可以通过一些流程控制语句来控制语句的执行顺序。
	
代码块
	代码块是在大括号 {} 中所写的语句,以此将多条语句的集合视为一条语句来使用。
	例如:
    {
        var a = 123;
        a++;
        alert(a);
    }
    我们一般使用代码块将需要一起执行的语句进行分组,需要注意的是,代码块结尾不需要加分号。
    
    es6语法 , let const 变量在代码块里只有局部作用,外面的代码看不到代码块内的let 变量

6. 流程控制语句(if-else if-else ;switch-case; while; do-while;for)

补充知识点
	prompt()可以弹出一个提示框,该提示框中会带有一个文本框,
	用户可以在文本框中输入一段内容,该函数需要一个字符串作为参数,
	该字符串将会作为提示框的提示文字
	用户输入的内容将会作为函数的返回值返回,可以定义一个变量来接收该内容
1.流程控制语句
	- 程序都是自上向下的顺序执行的,
		通过流程控制语句可以改变程序执行的顺序,或者反复的执行某一段的程序。
	- 分类:
		1.条件判断语句
		2.条件分支语句
		3.循环语句
		
	条件判断语句
		- 条件判断语句也称为if语句
		- 语法一:
			if(条件表达式){
				语句...
			}
			
			- 执行流程:
				if语句执行时,会先对条件表达式进行求值判断,
					如果值为true,则执行if后的语句
					如果值为false,则不执行
		
		- 语法二:
			if(条件表达式){
				语句...
			}else{
				语句...
			}
			
			- 执行流程:
				if...else语句执行时,会对条件表达式进行求值判断,
					如果值为true,则执行if后的语句
					如果值为false,则执行else后的语句
			
		- 语法三:
			if(条件表达式){
				语句...
			}else if(条件表达式){
				语句...
			}else if(条件表达式){
				语句...
			}else if(条件表达式){
				语句...
			}else{
				语句...
			}
			
			- 执行流程
				- if...else if...else语句执行时,会自上至下依次对条件表达式进行求值判断,
					如果判断结果为true,则执行当前if后的语句,执行完成后语句结束。
					如果判断结果为false,则继续向下判断,直到找到为true的为止。
					如果所有的条件表达式都是false,则执行else后的语句
1.条件分支语句
	- switch语句
	- 语法:
	- 这里需要与 case 全等 ===
		switch(条件表达式){
			case 表达式:
				语句...
				break;
			case 表达式:
				语句...
				break;
			case 表达式:
				语句...
				break;
			default:
				语句...
				break;
		}
		
	- 执行流程:
		- switch...case...语句在执行时,会依次将case后的表达式的值和switch后的表达式的值进行全等比较,
			如果比较结果为false,则继续向下比较。如果比较结果为true,则从当前case处开始向下执行代码。
			如果所有的case判断结果都为false,则从default处开始执行代码。
			
2.循环语句
	- 通过循环语句可以反复执行某些语句多次
	- while循环
		- 语法:
			while(条件表达式){
				语句...
			}
			
		- 执行流程:
			while语句在执行时,会先对条件表达式进行求值判断,
				如果判断结果为false,则终止循环
				如果判断结果为true,则执行循环体
				循环体执行完毕,继续对条件表达式进行求值判断,依此类推
				
	- do...while循环
		- 语法:
			do{
				语句...
			}while(条件表达式)
			
		- 执行流程
			do...while在执行时,会先执行do后的循环体,然后在对条件表达式进行判断,
				如果判断判断结果为false,则终止循环。
				如果判断结果为true,则继续执行循环体,依此类推
				
		- 和while的区别:
			while:先判断后执行
			do...while: 先执行后判断
			- do...while可以确保循环体至少执行一次。
			
			
	- for循环
		- 语法:
			for(①初始化表达式 ; ②条件表达式 ; ④更新表达式){
				③语句...
			}
		- 执行流程:
			首先执行①初始化表达式,初始化一个变量,
			然后对②条件表达式进行求值判断,如果为false则终止循环
			如果判断结果为true,则执行③循环体
			循环体执行完毕,执行④更新表达式,对变量进行更新。
			更新表达式执行完毕重复②
			
	- 死循环
		while(true){
		
		}
		
		for(;;){
		
		}

1.break-continue

 break关键字可以用来退出switch或循环语句
 不能在if语句中使用break和continue
 break关键字,会立即终止离他最近的那个循环语句
 
 可以为循环语句创建一个label,来标识当前的循环
 	label:循环语句
 	使用break语句时,可以在break后跟着一个label,
 	这样break将会结束指定的循环,而不是最近的
 	
 continue关键字可以用来跳过当次循环
 同样continue也是默认只会对离他最近的循环循环起作用
 	continue 也能配合label使用
 	

2.补充 程序计时-开方

console.time("计时器的名字")可以用来开启一个计时器
它需要一个字符串作为参数,这个字符串将会作为计时器的标识
console.timeEnd()用来停止一个计时器,需要一个计时器的名字作为参数
	例如:
		console.time("test");
		console.timeEnd("test");

可以通过Math.sqrt()对一个数进行开方

7.对象

对象分类
	1.内建对象
		- 由ES标准中定义的对象,在任何的ES的实现中都可以使用
		- 比如:Math String Number Boolean Function Object....
	2.宿主对象
		- 由JS的运行环境提供的对象,目前来讲主要指由浏览器提供的对象
		- 比如 BOM DOM
	3.自定义对象
		- 由开发人员自己创建的对象
		
1.对象(Object)
	- 对象是JS中的引用数据类型
	- 对象是一种复合数据类型,在对象中可以保存多个不同数据类型的属性
	- 使用typeof检查一个对象时,会返回object
	- 创建对象
		- 方式一:
			- var obj = new Object();
		- 方式二:使用对象字面量
			- var obj = {};
			
	- 向对象中添加属性
		- 语法:
			对象.属性名 = 属性值;
			对象["属性名"] = 属性值;
			
			- 对象的属性名没有任何要求,不需要遵守标识符的规范,
				但是在开发中,尽量按照标识符的要求去写。
			- 属性值也可以任意的数据类型。

	- 读取对象中的属性
		- 语法:
			对象.属性名
			对象["属性名"]
		- 如果读取一个对象中没有的属性,它不会报错,而是返回一个undefined
		
	- 删除对象中的属性
		- 语法:
			delete 对象.属性名
			delete 对象["属性名"]
			
	- 使用in检查对象中是否含有指定属性
		- 语法:"属性名" in 对象
			- 如果在对象中含有该属性,则返回true
				如果没有则返回false
				
	- 使用对象字面量,在创建对象时直接向对象中添加属性
		语法:
			var obj = {
							属性名:属性值,
							属性名:属性值,
							属性名:属性值,
							属性名:属性值
					}
	- 使用工厂方法创建对象 通过该方法可以大批量的创建对象
		使用工厂方法创建的对象,使用的构造函数都是Object
		就导致我们无法区分出多种不同类型的对象,后面用构造函数解决
		
			function createPerson(name , age ,gender){
				//创建一个新的对象 
				var obj = new Object();
				//向对象中添加属性
				obj.name = name;
				obj.age = age;
				obj.gender = gender;
				obj.sayName = function(){
					alert(this.name);
				};
				//将新的对象返回
				return obj;
			}
					
	- 基本数据类型和引用数据类型
		- 基本数据类型
			String Number Boolean Null Undefined
		- 引用数据类型
			Object
		- 基本数据类型的数据,变量是直接保存的它的值。
			变量与变量之间是互相独立的,修改一个变量不会影响其他的变量。
		- 引用数据类型的数据,变量是保存的对象的引用(内存地址)。
			如果多个变量指向的是同一个对象,此时修改一个变量的属性,会影响其他的变量。
		- 比较两个变量时,对于基本数据类型,比较的就是值,
			对于引用数据类型比较的是地址,地址相同才相同

8.函数

1.函数(Function)	
	- 函数也是一个对象,也具有普通对象的功能
	- 函数中可以封装一些代码,在需要的时候可以去调用函数来执行这些代码
	- 使用typeof检查一个函数时会返回function
	- 创建函数
	    - 构造函数
            //我们在实际开发中很少使用构造函数来创建一个函数对象
            //创建一个函数对象
            //可以将要封装的代码以字符串的形式传递给构造函数
            //var fun = new Function("console.log('Hello 这是我的第一个函数');");
		- 函数声明
			function 函数名([形参1,形参2...形参N]){
				语句...
			}
		
		- 函数表达式
			var 函数名 = function([形参1,形参2...形参N]){
				语句...
				//这是匿名函数 function 后面没有函数名
			};
			
	- 调用函数
		- 语法:函数对象([实参1,实参2...实参N]);
			fun() sum() alert() Number() parseInt()
		- 当我们调用函数时,函数中封装的代码会按照编写的顺序执行

	- 形参和实参
		- 形参:形式参数
			- 定义函数时,可以在()中定义一个或多个形参,形参之间使用,隔开
				定义形参就相当于在函数内声明了对应的变量但是并不赋值,
				形参会在调用时才赋值。
				
		- 实参:实际参数
			- 调用函数时,可以在()传递实参,传递的实参会赋值给对应的形参,
				调用函数时JS解析器不会检查实参的类型和个数,可以传递任意数据类型的值。
				如果实参的数量大于形参,多余实参将不会赋值,
				如果实参的数量小于形参,则没有对应实参的形参将会赋值undefined
				
        - 返回值,就是函数执行的结果。
            - 使用return 来设置函数的返回值。
            - 语法:return 值;
                - 该值就会成为函数的返回值,可以通过一个变量来接收返回值
            - return后边的代码都不会执行,一旦执行到return语句时,函数将会立刻退出。
            - return后可以跟任意类型的值,可以是基本数据类型,也可以是一个对象。
            - 如果return后不跟值,或者是不写return则函数默认返回undefined。
            - break、continue和return
                - break
                    - 退出循环
                - continue
                    - 跳过当次循环
                - return
                    - 退出函数

        - 参数,函数的实参也可以是任意的数据类型。

        - 方法(method)
            - 可以将一个函数设置为一个对象的属性,
                当一个对象的属性是一个函数时,
                    我们称这个函数是该对象的方法。
            - 对象.方法名();
            - 函数名();	

补充 立即执行函数

/*
* 立即执行函数
* 	函数定义完,立即被调用,这种函数叫做立即执行函数
* 	立即执行函数往往只会执行一次
*/


(function () {
	alert("我是一个匿名函数~~~");
})();

(function (a, b) {
	console.log("a = " + a);
	console.log("b = " + b);
})(123, 456);

(function () {
	alert("我是一个匿名函数~~~");
}());

(function (a, b) {
	console.log("a = " + a);
	console.log("b = " + b);
}(123, 456));

9.作用域

作用域
	- 作用域简单来说就是一个变量的作用范围。
	- 在JS中作用域分成两种:
		1.全局作用域
			- 直接在script标签中编写的代码都运行在全局作用域中
			- 全局作用域在打开页面时创建,在页面关闭时销毁。
			- 全局作用域中有一个全局对象window,window对象由浏览器提供,
				可以在页面中直接使用,它代表的是整个的浏览器的窗口。
			- 在全局作用域中创建的变量都会作为window对象的属性保存
				在全局作用域中创建的函数都会作为window对象的方法保存
			- 在全局作用域中创建的变量和函数可以在页面的任意位置访问。
				在函数作用域中也可以访问到全局作用域的变量。
			- 尽量不要在全局中创建变量	
		
		2.函数作用域
			- 函数作用域是函数执行时创建的作用域,每次调用函数都会创建一个新的函数作用域。
			- 函数作用域在函数执行时创建,在函数执行结束时销毁。
			- 在函数作用域中创建的变量,不能在全局中访问。
			- 当在函数作用域中使用一个变量时,它会先在自身作用域中寻找,
				如果找到了则直接使用,如果没有找到则到上一级作用域中寻找,
					如果找到了则使用,找不到则继续向上找,一直会
					
		- 变量的声明提前
			- 在全局作用域中,使用var关键字声明的变量会在所有的代码执行之前被声明,但是不会赋值。
				所以我们可以在变量声明前使用变量。但是不使用var关键字声明的变量不会被声明提前。
			- 在函数作用域中,也具有该特性,使用var关键字声明的变量会在函数所有的代码执行前被声明,
				****如果没有使用var关键字声明变量,则变量会变成全局变量,不使用var关键字声明的变量不会被声明提前。
				
		- 函数的声明提前
			- 在全局作用域中,使用函数声明创建的函数(function fun(){}),会在所有的代码执行之前被创建,
				也就是我们可以在函数声明前去调用函数,但是使用函数表达式(var fun = function(){})创建的函数没有该特性
			- 在函数作用域中,使用函数声明创建的函数,会在所有的函数中的代码执行之前就被创建好了。

10.this(上下文对象)

	- 我们每次调用函数时,解析器都会将一个上下文对象作为隐含的参数传递进函数。
		使用this来引用上下文对象,根据函数的调用形式不同,this的值也不同。
	- this的不同的情况:
		1.以函数的形式调用时,this是window
		2.以方法的形式调用时,this就是调用方法的对象
		3.以构造函数的形式调用时,this就是新创建的对象
		4.使用call和apply调用时,this是指定的那个对象
		5.在全局作用域中this代表window
目前以我自己知识量对this指向的总结

1.**以函数的形式调用时,this是window**
2.以方法的形式调用时,this就是调用方法的对象
3.以构造函数的形式调用时,this就是新创建的对象

函数箭头函数没有自己的this对象,看他所在作用域的this。
bind 可以绑定 普通函数的this对象,不可以绑定箭头函数的
箭头函数内部的this指向是固定的,相比之下,普通函数的this指向是可变的。
**普通函数**只有作为某**对象方法**时,内部this是这个对象,其余全是window ,构造函数作为普通函数使用 this 指向 window
构造函数new方式使用,this就是新创建的对象。

如下代码 输出的this 指向 window
        var test = {
            id: 1,
            fun: function (fun1) {
                fun1()
            }
        }
        var obj = {
            id: 2,
            fun: function () {
                test.fun(function () { console.log(this); })
            }
        }
        obj.fun()

补充:
4.使用call和apply调用时,this是指定的那个对象,不可以改变箭头函数的this指向
5.在全局作用域中this代表window

	- call()
	- apply()
		- 这两个方法都是函数对象的方法需要通过函数对象来调用
		- 通过两个方法可以直接调用函数,并且可以通过第一个实参来指定函数中this
		- 不同的是call是直接传递函数的实参而apply需要将实参封装到一个数组中传递
		- call()方法可以将实参在对象之后依次传递
		- apply()方法需要将实参封装到一个数组中统一传递

11.构造函数

	- 构造函数是专门用来创建对象的函数
	- 一个构造函数我们也可以称为一个类
	- 通过一个构造函数创建的对象,我们称该对象时这个构造函数的实例
	- 通过同一个构造函数创建的对象,我们称为一类对象
	- 构造函数就是一个普通的函数,只是他的调用方式不同,
		如果直接调用,它就是一个普通函数
		如果使用new来调用,则它就是一个构造函数
		
	- 例子:
		function Person(){
		
		}
		
	- 构造函数的执行流程:
		1.创建一个新的对象
		2.将新的对象作为函数的上下文对象(this)
		3.执行函数中的代码
		4.将新建的对象返回
		
	- 
		
	- instanceof 用来检查一个对象是否是一个类的实例
		- 语法:对象 instanceof 构造函数
			- 如果该对象时构造函数的实例,则返回true,否则返回false
			- Object是所有对象的祖先,所以任何对象和Object做instanceof都会返回true
			
			/*
			 * 创建一个Person构造函数
			 * 	- 在Person构造函数中,为每一个对象都添加了一个sayName方法,
			 * 		目前我们的方法是在构造函数内部创建的,
			 * 			也就是构造函数每执行一次就会创建一个新的sayName方法
			 * 		也是所有实例的sayName都是唯一的。
			 * 		这样就导致了构造函数执行一次就会创建一个新的方法,
			 * 			执行10000次就会创建10000个新的方法,而10000个方法都是一摸一样的
			 * 			这是完全没有必要,完全可以使所有的对象共享同一个方法
			 */
			function Person(name , age , gender){
				this.name = name;
				this.age = age;
				this.gender = gender;
				//向对象中添加一个方法
				this.sayName = function(){
					alert("Hello大家好,我是:"+this.name);
				}
				
			}

			//将sayName方法在全局作用域中定义
			/*
			 * 将函数定义在全局作用域,污染了全局作用域的命名空间
			 * 	而且定义在全局作用域中也很不安全
			 */
			function Person(name , age , gender){
				this.name = name;
				this.age = age;
				this.gender = gender;
				//向对象中添加一个方法
				this.sayName = fun;
			}

			function fun(){
				alert("Hello大家好,我是:"+this.name);
			};

			//向原型中添加sayName方法 √
			Person.prototype.sayName = function(){
				alert("Hello大家好,我是:"+this.name);
			};

1.枚举对象中的属性

		for...in
		语法:
			for(var 属性名 in 对象){
			
			}
			
		for...in语句的循环体会执行多次,对象中有几个属性就会执行几次(包括自己在构造函数在原型对象中添加的属性),
			每次将一个属性名赋值给我们定义的变量,我们可以通过它来获取对象中的属性
			
	如果是数组,对应的属性名是从0开始的索引
	
for...of语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句

12.原型

1.原型(prototype)
   - 创建一个函数以后,**解析器**都会**默认在函数中添加一个数prototype**
		prototype属性指向的是一个对象,这个对象我们称为原型对象。
		如果函数作为普通函数调用prototype没有任何作用
   - 当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性,
   		指向该构造函数的原型对象,我们可以通过__proto__来访问该属性
	
   - 原型对象就相当于一个公共的区域,凡是通过同一个构造函数创建的对象他们通常都可以访问到相同的原型对象。
		我们可以将对象中共有的属性和方法统一添加到原型对象中,
			这样我们只需要添加一次,就可以使所有的对象都可以使用。
	- 当我们去访问对象的一个属性或调用对象的一个方法时,它会先自身中寻找,
		如果在自身中找到了,则直接使用。
		如果没有找到,则去原型对象中寻找,如果找到了则使用,
		如果没有找到,则去原型的原型中寻找,依此类推。直到找到Object的原型为止,Object的原型的原型为null,
		如果依然没有找到则返回undefined
		
	- 以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,
		这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了

	- hasOwnProperty()
		- 这个方法可以用来检查对象自身中是否含有某个属性(原型身上的不算)
		- 语法:对象.hasOwnProperty("属性名")

1.补充 toString

当我们直接在页面中打印一个对象时,事件上是输出的对象的toString()方法的返回值
如果我们希望在输出对象时不输出[object Object],可以为对象添加一个toString()方法
一般加在构造函数prototype上

2.垃圾回收(GC)

- 就像人生活的时间长了会产生垃圾一样,程序运行过程中也会产生垃圾
		这些垃圾积攒过多以后,会导致程序运行的速度过慢,
		所以我们需要一个垃圾回收的机制,来处理程序运行过程中产生垃圾
- 当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法操作该对象,
		此时这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢,
		所以这种垃圾必须进行清理。
- 在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,
		我们不需要也不能进行垃圾回收的操作
- **我们需要做的只是要将不再使用的对象设置null即可**

13.数组

数组(Array)
	- 数组也是一个对象,是一个用来存储数据的对象
		和Object类似,但是它的存储效率比普通对象要高
		数组中的元素可以是任意的数据类型
		数组中也可以放数组,生成多维数组
	- 数组中保存的内容我们称为元素	
	- 数组使用索引(index)来操作元素
	- 索引指由0开始的整数
	- 数组的操作:
		- 创建数组
			- var arr = new Array();
			- var arr = [];
			
		- 向数组中添加元素
			- 语法;
				数组对象[索引] = 值;
				arr[0] = 123;
				arr[1] = "hello";
				
		- 创建数组时直接添加元素
			- 语法:
				var arr = [元素1,元素2....元素N];
				var arr = new Array(1, 'a', null);
				 new Array(3) 创建长度为3的空数组
				- 例子:
					var arr = [123,"hello",true,null];
					
		- 获取和修改数组的长度
			- 使用length属性来操作数组的长度
			- 获取长度:
				数组.length
				- length获取到的是数组的最大索引+1
				- 对于连续的数组,length获取到的就是数组中元素的个数
			- 修改数组的长度
				数组.length = 新长度
					- 如果修改后的length大于原长度,则多出的部分会空出来
					- 如果修改后的length小于原长度,则原数组中多出的元素会被删除
			- 向数组的最后添加元素
				数组[数组.length] = 值;
				
	- 数组的方法
		- push()
			- 用来向数组的末尾添加一个或多个元素,并返回数组新的长度
			- 语法:数组.push(元素1,元素2,元素N)
		- pop()
			- 用来删除数组的最后一个元素,并返回被删除的元素
		- unshift()
			- 向数组的前边添加一个或多个元素,并返回数组的新的长度
		- shift()
			- 删除数组的前边的一个元素,并返回被删除的元素
		- slice()
			- 可以从一个数组中截取指定的元素
			- 该方法不会影响原数组,而是将截取到的内容封装为一个新的数组并返回
			- 参数:
				1.截取开始位置的索引(包括开始位置)
				2.截取结束位置的索引(不包括结束位置)
					- 第二个参数可以省略不写,如果不写则一直截取到最后
				- 参数可以传递一个负值,如果是负值,则从后往前数
		- splice()
			- 可以用来删除数组中指定元素,并使用新的元素替换
				该方法会将删除的元素封装到新数组中返回
			- 参数:
				1.删除开始位置的索引
				2.删除的个数
				3.三个以后,都是替换的元素,这些元素将会插入到开始位置索引的前边
				
	- 遍历数组
		- 遍历数组就是将数组中元素都获取到
		- 一般情况我们都是使用for循环来遍历数组:
			for(var i=0 ; i<数组.length ; i++){
				//数组[i]
			}
			
		- 使用forEach()方法来遍历数组(不兼容IE8)
		
			数组.forEach(function(value , index , obj){
			
			});
			
			forEach()方法需要一个回调函数作为参数,
				数组中有几个元素,回调函数就会被调用几次,
				每次调用时,都会将遍历到的信息以实参的形式传递进来,
				我们可以定义形参来获取这些信息。
				value:正在遍历的元素
				index:正在遍历元素的索引
				obj:被遍历对象

14.数组方法

	reverse()
		- reverse() 方法将数组中元素的位置颠倒,并返回该数组。数组的第一个元素会变成最后一个,数组的最后一个元素变成第一个。该方法会改变原数组。
	concat()
		- 可以连接两个或多个数组,它不会影响原数组,而是新数组作为返回值返回
			该方法不会对原数组产生影响
	join()
		- 可以将一个数组转换为一个字符串
		- 参数:
			需要一个字符串作为参数,这个字符串将会作为连接符来连接数组中的元素
			如果不指定连接符则默认使用','
	sort()
		- 可以对一个数组中的内容进行排序,默认是按照'Unicode编码'进行排序
			调用以后,会直接修改原数组。
		- 即使数组是数字数组,也默认Unicode 编码排序
		- 可以自己指定排序的规则,需要一个回调函数作为参数:
			function(a,b){
				
				//升序排列
				//return a-b;
				
				//降序排列
				return b-a;
			}
方法描述
push()将新元素添加到数组的末尾,并返回新的长度。
pop()删除数组的最后一个元素,并返回该元素。
shift()删除数组的第一个元素,并返回该元素。
unshift()将新元素添加到数组的开头,并返回新的长度。
forEach()为每个数组元素调用函数。
slice()选择数组的一部分,并返回新数组。
splice()从数组中添加/删除元素。
concat()连接两个或多个数组,并返回已连接数组的副本。
reverse()反转数组中元素的顺序。
join()将数组的所有元素连接成一个字符串。
sort()对数组的元素进行排序。
copyWithin()将数组中的数组元素复制到指定位置或从指定位置复制。
entries()返回键/值对数组迭代对象。
every()检查数组中的每个元素是否通过测试。
fill()用静态值填充数组中的元素。
filter()使用数组中通过测试的每个元素创建新数组。
find()返回数组中第一个通过测试的元素的值。
findIndex()返回数组中通过测试的第一个元素的索引。
from()从对象创建数组。
includes()检查数组是否包含指定的元素。
indexOf()在数组中搜索元素并返回其位置。
isArray()检查对象是否为数组。
keys()返回 Array Iteration 对象,包含原始数组的键.
lastIndexOf()在数组中搜索元素,从末尾开始,并返回其位置。
map()使用为每个数组元素调用函数的结果创建新数组。
reduce()将数组的值减为单个值(从左到右)。
reduceRight()将数组的值减为单个值(从右到左)。
some()检查数组中的任何元素是否通过测试。
toString()将数组转换为字符串,并返回结果。
valueOf()返回数组的原始值。

15.函数方法call-apply-arguments[callee]

	- call()
	- apply()
		- 这两个方法都是函数对象的方法需要通过函数对象来调用
		- 通过两个方法可以直接调用函数,并且可以通过第一个实参来指定函数中this
		- 不同的是call是直接传递函数的实参而apply需要将实参封装到一个数组中传递
		- call()方法可以将实参在对象之后依次传递
		- apply()方法需要将实参封装到一个数组中统一传递
	- arguments
		- arguments和this类似,都是函数中的隐含的参数
		- arguments是一个*类数组元素*,它用来封装函数执行过程中的实参
			所以即使不定义形参,也可以通过arguments来使用实参
		- arguments中有一个属性callee表示当前执行的函数对象
		

1.补充:闭包

闭包(closure) 
	- 闭包是JS一个非常重要的特性,这意味着当前作用域总是能够访问外部作用域中的
		变量。因为函数是JS中唯一拥有自身作用域的结构,因此闭包的创建依赖于函数。
	- 也可以将闭包的特征理解为,其相关的局部变量在函数调用结束之后将会继续存在。

16.包装类

	- 在JS中为我们提供了三个包装类:
		String() Boolean() Number()
		- 通过这三个包装类可以创建基本数据类型的对象
		例子:
			var num = new Number(2);
			var str = new String("hello");
			var bool = new Boolean(true);
		- 但是在实际应用中千万不要这么干。
	
	- 当我们去操作一个基本数据类型的属性和方法时,
		解析器会临时将其转换为对应的包装类,然后再去操作属性和方法,
		操作完成以后再将这个临时对象进行销毁。

17.字符串的相关的方法

在底层字符串是以字符数组的形式保存的	
			//console.log(str.length);
			//console.log(str[5]);
	length
		- 获取字符串的长度
	charAt()
		- 根据索引获取指定的字符
	charCodeAt()
		- 根据索引获取指定的字符编码
	String.fromCharCode()
		- 根据字符编码获取字符
	concat()
		- 可以用来连接两个或多个字符串
		- 作用和+一样
	indexOf() 
	lastIndexOf()
		- 从一个字符串中检索指定内容
		- 需要一个字符串作为参数,这个字符串就是要检索的内容,
			如果找到该内容,则会返回其第一次出现的索引,如果没有找到则返回-1。
		- 可以指定一个第二个参数,来表示开始查找的位置 ,不能指定负数
		- indexOf()是从前向后找
		- lastIndexOf()是从后向前找
	slice()
		- 可以从一个字符串中截取指定的内容,并将截取到内容返回,不会影响原变量
		- 参数:
			第一个:截取开始的位置(包括开始)
			第二个:截取结束的位置(不包括结束)
				- 可以省略第二个参数,如果省略则一直截取到最后
			- 可以传负数,如果是负数则从后往前数
	substr()	
		- 和slice()基本一致,不同的是它第二个参数不是索引,而是截取的数量
		
	substring()
		- 和slice()基本一致,不同的是它不能接受负值作为参数,如果设置一个负值,则会自动修正为0,
			substring()中如果第二个参数小于第一个,自动调整位置
	toLowerCase() toLocaleLowerCase()
		- 将字符串转换为小写并返回
	toUpperCase() toLocaleUpperCase()
		- 将字符串转换为大写并返回
	split()
		- 可以根据指定内容将一个字符串拆分为一个数组
		- 参数:
			- 需要一个字符串作为参数,将会根据字符串去拆分数组
				可以接收一个正则表达式,此时会根据正则表达式去拆分数组
				

方法描述
anchor()创建 HTML 锚。
big()用大号字体显示字符串。
blink()显示闪动字符串。
bold()使用粗体显示字符串。
charAt()返回在指定位置的字符。
charCodeAt()返回在指定的位置的字符的 Unicode 编码。
concat()连接字符串。
fixed()以打字机文本显示字符串。
fontcolor()使用指定的颜色来显示字符串。
fontsize()使用指定的尺寸来显示字符串。
fromCharCode()从字符编码创建一个字符串。
indexOf()检索字符串。
italics()使用斜体显示字符串。
lastIndexOf()从后向前搜索字符串。
link()将字符串显示为链接。
localeCompare()用本地特定的顺序来比较两个字符串。
match()找到一个或多个正则表达式的匹配。
replace()替换与正则表达式匹配的子串。
search()检索与正则表达式相匹配的值。
slice()提取字符串的片断,并在新的字符串中返回被提取的部分。
small()使用小字号来显示字符串。
split()把字符串分割为字符串数组。
strike()使用删除线来显示字符串。
sub()把字符串显示为下标。
substr()从起始索引号提取字符串中指定数目的字符。
substring()提取字符串中两个指定的索引号之间的字符。
sup()把字符串显示为上标。
toLocaleLowerCase()把字符串转换为小写。
toLocaleUpperCase()把字符串转换为大写。
toLowerCase()把字符串转换为小写。
toUpperCase()把字符串转换为大写。
toSource()代表对象的源代码。
toString()返回字符串。
valueOf()返回某个字符串对象的原始值。

18.正则表达式

正则表达式快速掌握包括贪婪与懒惰匹配

方法描述
exec一个在字符串中执行查找匹配的RegExp方法,它返回一个数组(只有索引为零的值)(未匹配到则返回 null)【一次查一个 迭代使用】。
test一个在字符串中测试是否匹配的RegExp方法,它返回 true 或 false。
match一个在字符串中执行查找匹配的String方法,它返回一个数组,在未匹配到时会返回 null。
matchAll一个在字符串中执行查找所有匹配的String方法,它返回一个迭代器(iterator)。
search一个在字符串中测试匹配的String方法,它返回匹配到的位置索引,或者在失败时返回-1。
replace一个在字符串中执行查找匹配的String方法,并且使用替换字符串替换掉匹配到的子字符串。
split一个使用正则表达式或者一个固定字符串分隔一个字符串,并将分隔后的子字符串存储到数组中的 String 方法。
	- 正则用来定义一些字符串的规则,程序可以根据这些规则来判断一个字符串是否符合规则,
		也可以将一个字符串中符合规则的内容提取出来。
	- 创建正则表达式
		- var reg = new RegExp("正则","匹配模式");
		- var reg = /正则表达式/匹配模式
		
		下面这是两两等价 注意一下
        var reg = /\./
        var reg = RegExp('\\.')
        var reg = /\\/
        var reg = RegExp('\\\\')
	- 语法:
		匹配模式:
			i:忽略大小写
			g:全局匹配模式
			- 设置匹配模式时,可以都不设置,也可以设置1个,也可以全设置,设置时没有顺序要求
			
		正则语法		
			| 或
			[] 或
			[^ ] 除了
			[a-z] 小写字母
			[A-Z] 大写字母
			[A-z] 任意字母
			[0-9] 任意数字

	- 语法:
		- 量词
			{n} 正好n次
			{m,n} m-n次
			{m,} 至少m次
			+	至少1次 {1,}
			?   0次或1次 {0,1}
			*   0次或多次 {0,}
			
		- 转义字符
			\ 在正则表达式中使用\作为转义字符
			\. 表示.
			\\ 表示\
			. 表示任意字符
			\w
				- 相当于[A-z0-9_]
			\W
				- 相当于[^A-z0-9_]
			\d
				- 任意数字
			\D
				- 除了数字
			\s
				- 空格
			\S
				- 除了空格
			\b
				- 单词边界  
				下列都有/\bword\b/
				'word' '#word%' 
				下列无/\bword\b/
				'_word' '1word'
				边界不能为 \w   相当于[A-z0-9_]
			\B
				- 除了单词边界
		^ 表示开始
		$ 表示结束	
        
        
        
        
	- 方法:
		test()
			- 可以用来检查一个字符串是否符合正则表达式
			- 如果符合返回true,否则返回false
			
	match() 
		- 可以将字符串中和正则表达式匹配的内容提取出来
		- 默认情况下我们的match只会找到第一个符合要求的内容,找到以后就停止检索
			我们可以设置正则表达式为全局匹配模式,这样就会匹配到所有的内容
			以为一个正则表达式设置多个匹配模式,且顺序无所谓
		- match()会将匹配到的内容封装到一个数组中返回,即使只查询到一个结果			
		- 参数:
			- 正则表达式,可以根据该正则表达式将字符串中符合要求的内容提取出来
					并且封装到一个数组中返回
	
	replace()  
		- 可以将字符串中指定内容替换为新的内容
		- 参数:
			- 第一个:被替换的内容,可以是一个正则表达式
			- 第二个:替换的新内容
		- 默认只会替换第一个 ,可以设置为全局匹配
			
	search() 
		- 可以根据正则表达式去字符串中查找指定的内容
		- 可以搜索字符串中是否含有指定内容
		- 参数:
			正则表达式(也可以为字符串,但是有indexOf),将会根据该表达式查询内容,
			并且将第一个匹配到的内容的索引返回,如果没有匹配到任何内容,则返回-1。
	split()
		- 可以根据指定内容将一个字符串拆分为一个数组
		- 参数:
			- 需要一个字符串作为参数,将会根据字符串去拆分数组
				可以接收一个正则表达式,此时会根据正则表达式去拆分数组
				这个方法即使不指定全局匹配,也会全都插分

请添加图片描述

19.Date

	- 日期的对象,在JS中通过Date对象来表示一个时间
	- 创建对象
		- 创建一个当前的时间对象
			var d = new Date();
		- 创建一个指定的时间对象
			var d = new Date("月/日/年 时:分:秒");
			
	- 方法:
		getDate()
			- 当前日期对象是几日(1-31)
			
		getDay() 
			- 返回当前日期对象时周几(0-6)
				- 0 周日
				- 1 周一 。。。
				
		getMonth()
			- 返回当前日期对象的月份(0-11)
			- 0 一月 1 二月 。。。
		getFullYear() 从 Date 对象以四位数字返回年份。 
		
		getHours() 返回 Date 对象的小时 (0 ~ 23)。 
		getMinutes() 返回 Date 对象的分钟 (0 ~ 59)。 
		getSeconds() 返回 Date 对象的秒数 (0 ~ 59)。 
		getMilliseconds() 返回 Date 对象的毫秒(0 ~ 999)。 
		
		getTime()
			- 返回当前日期对象的时间戳
			- 时间戳,指的是从1970年1月1日 0时0分0秒,到现在时间的毫秒数
				计算机底层保存时间都是以时间戳的形式保存的。
				
		Date.now()
			- 可以获取当前代码执行时的时间戳

20.Math

	- Math属于一个工具类,它不需要我们创建对象,它里边封装了属性运算相关的常量和方法
		我们可以直接使用它来进行数学运算相关的操作
	- 方法:
		Math.PI
			- 常量,圆周率
		Math.abs()
			- 绝对值运算
		Math.ceil()
			- 向上取整
		Math.floor()
			- 向下取整
		Math.round()
			- 四舍五入取整
		Math.random()	
			- 生成一个0-1之间的随机数 没有0和1
			- 生成一个x-y之间的随机整数
				Math.floor(Math.random()*(y+1-x)+x);
		Math.pow(x,y)
			- 求x的y次幂
			- x ** y
		Math.sqrt()
			- 对一个数进行开方
		Math.max()
			- 求多个数中最大值
		Math.min()
			- 求多个数中的最小值




21.JSON

JavaScript 的json源码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		
		<!--
			如果需要兼容IE7及以下的JSON操作,则可以通过引入一个外部的js文件来处理
		-->
		<script type="text/javascript" src="js/json2.js"></script>
		<script type="text/javascript">
			
			/*
			 * JSON
			 * 	- JS中的对象只有JS自己认识,其他的语言都不认识
			 * 	- JSON就是一个特殊格式的字符串,这个字符串可以被任意的语言所识别,
			 * 		并且可以转换为任意语言中的对象,JSON在开发中主要用来数据的交互
			 * 	- JSON
			 * 		- JavaScript Object Notation JS对象表示法
			 * 		- JSON和JS对象的格式一样,只不过JSON字符串中的属性名必须加双引号
			 * 			其他的和JS语法一致
			 * 		JSON分类:
			 * 			1.对象 {}
			 * 			2.数组 []
			 * 
			 * 		JSON中允许的值:
			 * 			1.字符串
			 * 			2.数值
			 * 			3.布尔值
			 * 			4.null
			 * 			5.对象
			 * 			6.数组
			 */
			
			//创建一个对象
			
			
			var arr = '[1,2,3,"hello",true]';
			
			var obj2 = '{"arr":[1,2,3]}';
			
			var arr2 ='[{"name":"孙悟空","age":18,"gender":"男"},{"name":"孙悟空","age":18,"gender":"男"}]';
			
			/*
			 * 将JSON字符串转换为JS中的对象
			 * 	在JS中,为我们提供了一个工具类,就叫JSON
			 * 	这个对象可以帮助我们将一个JSON转换为JS对象,也可以将一个JS对象转换为JSON
			 */
			
			var json = '{"name":"孙悟空","age":18,"gender":"男"}';
			
			/*
			 * json --> js对象
			 * 	 JSON.parse()
			 * 		- 可以将以JSON字符串转换为js对象
			 * 		- 它需要一个JSON字符串作为参数,会将该字符串转换为JS对象并返回
			 */
			
			var o = JSON.parse(json);
			var o2 = JSON.parse(arr);
			
			//console.log(o.gender);
			//console.log(o2[1]);
			
			var obj3 = {name:"猪八戒" , age:28 , gender:"男"};
			
			
			/*
			 * JS对象 ---> JSON
			 * 	JSON.stringify()
			 * 		- 可以将一个JS对象转换为JSON字符串
			 * 		- 需要一个js对象作为参数,会返回一个JSON字符串
			 */
			
			var str = JSON.stringify(obj3);
			//console.log(str);
			
			/*
			 * JSON这个对象在IE7及以下的浏览器中不支持,所以在这些浏览器中调用时会报错
			 */
			
			
			var str3 = '{"name":"孙悟空","age":18,"gender":"男"}';
			
			JSON.parse(str3);
			
			
			
			
		</script>
	</head>
	<body>
	</body>
</html>

IE7及以下的浏览器的JSON字符串转为对象格式

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<script type="text/javascript">
		
			var str = '{"name":"孙悟空","age":18,"gender":"男"}';
			
			/*
			 * eval()
			 * 	- 这个函数可以用来执行一段字符串形式的JS代码,并将执行结果返回
			 * 	- 如果使用eval()执行的字符串中含有{},它会将{}当成是代码块
			 * 		如果不希望将其当成代码块解析,则需要在字符串前后各加一个()
			 * 
			 * 	- eval()这个函数的功能很强大,可以直接执行一个字符串中的js代码,
			 * 		但是在开发中尽量不要使用,首先它的执行性能比较差,然后它还具有安全隐患
			 */
			
			var str2 = "alert('hello');";
			
			var obj = eval("("+str+")");
			
			//console.log(obj);
			
			
			
		</script>
	</head>
	<body>
	</body>
</html>

三、DOM

1.什么是DOM

  • DOM,全称Document Object Model文档对象模型。

  • JS中通过DOM来对HTML文档进行操作。只要理解了DOM就可以随心所欲的操作WEB页面。

  • 文档

    – 文档表示的就是整个的HTML网页文档

  • 对象

    – 对象表示将网页中的每一个部分都转换为了一个对象。

    • 转换完对象以后,就可以以一种纯面向对象的形式来操作网页了
  • 模型

    – 使用模型来表示对象之间的关系,这样方便我们获取对象。

    image-20220223225659943

2.节点

  • 节点Node,是构成我们网页的最基本的组成部分,网页中每一个部分都可以称为是一个节点。

  • 比如:html标签、属性、文本、注释、整个文档等都是一个节点。

  • 虽然都是节点,但是实际上他们的具体类型是不同的。

  • 比如:标签我们称为元素节点、属性称为属性节点、文本称为文本节点、文档称为文档节点。

  • 节点的类型不同,属性和方法也都不尽相同。

节点的属性

image-20220223230037885

文档节点(document)

  • 文档节点document,代表的是整个HTML文档,网页中的所有节点都是它的子节点。

  • document对象作为window对象的属性存在的,我们不用获取可以直接使用。

  • 通过该对象我们可以在整个文档访问内查找节点对象,并可以通过该对象创建各种节点对象。

元素节点(Element)

  • HTML中的各种标签都是元素节点,这也是我们最常用的一个节点。

  • 浏览器会将页面中所有的标签都转换为一个元素节点,我们可以通过document的方法来获取元素节点。

  • 比如:

    – document.getElementById()

    – 根据id属性值获取一个元素节点对象。

文本节点(Text)

  • 文本节点表示的是HTML标签以外的文本内容,任意非HTML的文本都是文本节点。

  • 它包括可以字面解释的纯文本内容。

  • 文本节点一般是作为元素节点的子节点存在的。

  • 获取文本节点时,一般先要获取元素节点。在通过元素节点获取文本节点。

  • 例如:

    元素节点.firstChild;

    – 获取元素节点的第一个子节点,一般为文本节点

属性节点(Attr

  • 属性节点表示的是标签中的一个一个的属性,这里要注意的是属性节点并非是元素节点的子节点,而是元素节点的一部分。

  • 可以通过元素节点来获取指定的属性节点。

  • 例如:

    元素节点.getAttributeNode("属性名");

    注意:我们一般不使用属性节点。

3.事件

  • 事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。

  • JavaScript 与 HTML 之间的交互是通过事件实现的。

  • 对于 Web 应用来说,有下面这些代表性的事件:点击某个元素、将鼠标移动至某个元素上方、按下键盘上某个键,等等。

4.获取节点

获取元素节点 – 通过document对象调用

  1. getElementById()

    – 通过id属性获取一个元素节点对象

  2. getElementsByTagName()

    – 通过标签名获取一组元素节点对象

  3. getElementsByName()只有document有

    – 通过name属性获取一组元素节点对象

  4. getElementsByClassName()

	- DOM操作
		- DOM查询
		- 在网页中浏览器已经为我们提供了document对象,
			它代表的是整个网页,它是window对象的属性,可以在页面中直接使用。
		- document查询方法:
			- 根据元素的id属性查询一个元素节点对象:
				- document.getElementById("id属性值");
			- 根据元素的name属性值查询一组元素节点对象:
				- document.getElementsByName("name属性值");
			- 根据标签名来查询一组元素节点对象:
				- document.getElementsByTagName("标签名");

获取元素节点的子节点 – 通过具体的元素节点调用

  1. getElementsByTagName()

    – 方法,返回当前节点的指定标签名后代节点

    getElementsByClassName

    – 方法,返回当前节点的指定类名后代节点

  2. childNodes

    – 属性,表示当前节点的所有子节点

  3. firstChild

    – 属性,表示当前节点的第一个子节点

    firstElementChild

    – 属性,表示当前节点的第一个元素子节点

  4. lastChild

    – 属性,表示当前节点的最后一个子节点

    lastElementChild

    – 属性,表示当前节点的最后一个元素子节点

  5. children

    – 获取当前元素的所有子元素

  6. 可以通过元素节点来获取指定的属性节点。

    元素节点.getAttributeNode("属性名");

    注意:我们一般不使用属性节点。

获取父节点和兄弟节点 – 通过具体的节点调用

  1. parentNode

    – 属性,表示当前节点的父节点

  2. previousSibling

    – 属性,表示当前节点的前一个兄弟节点

    previousElementSibling

    – 属性,表示当前节点的前一个兄弟节点

  3. nextSibling

    – 属性,表示当前节点的后一个元素兄弟节点

    nextElementSibling

    – 属性,表示当前节点的后一个元素兄弟节点

元素节点的属性

  • 获取,元素对象.属性名

  • 注意 属性classjs里面是className

    例:
    
        element.value
    
        element.id
    
        element.className
    
    
  • 设置,元素对象.属性名=新的值

    例:
        element.value = “hello”
    
        element.id = “id01”
    
        element.className = “newClass”
    
nodeValue-innerHTML-innerText

nodeValue

​ – 文本节点可以通过nodeValue属性获取和设置文本节点的内容

innerHTML

​ – 元素节点通过该属性获取和设置标签内部的html代码

	innerHTML和innerText
		- 这两个属性并没有在DOM标准定义,但是大部分浏览器都支持这两个属性
		- 两个属性作用类似,都可以获取到标签内部的内容,
			不同是innerHTML会获取到html标签,而innerText会自动去除标签
		- 如果使用这两个属性来设置标签内部的内容时,没有任何区别的	
	
	读取标签内部的文本内容
		<h1>h1中的文本内容</h1>
		元素.firstChild.nodeValue
其他属性
	- document对象的其他的属性和方法
		document.all
			- 获取页面中的所有元素,相当于document.getElementsByTagName("*");
			
		document.documentElement
			- 获取页面中html根元素
			
		document.body
			- 获取页面中的body元素
			
		document.getElementsByClassName()
			- 根据元素的class属性值查询一组元素节点对象
			- 这个方法不支持IE8及以下的浏览器

使用CSS选择器进行查询

  • querySelector()

  • querySelectorAll()

  • 这两个方法都是用document对象来调用,两个方法使用相同,都是传递一个选择器字符串作为参数,方法会自动根据选择器字符串去网页中查找元素。

  • 不同的地方是querySelector()只会返回找到的第一个元素,而querySelectorAll()会返回所有符合条件的元素。

5.节点的修改(DOM修改)

  • 这里的修改我们主要指对元素节点的操作。

  • 创建节点

    document.createElement(标签名)

  • 删除节点

    父节点.removeChild(子节点)

  • 替换节点

    父节点.replaceChild(新节点 , 旧节点)

  • 插入节点

    – 父节点.appendChild(子节点)

    – 父节点.insertBefore(新节点 , 旧节点)

DOM修改
	document.createElement()
		- 可以根据标签名创建一个元素节点对象
		
	document.createTextNode()
		- 可以根据文本内容创建一个文本节点对象
		
	父节点.appendChild(子节点)
		- 向父节点中添加指定的子节点
		- 若这个节点是页面上的,就把原位置节拿走放到指定父节点的里面
		
	父节点.insertBefore(新节点,旧节点)
		- 将一个新的节点插入到旧节点的前边
		
	父节点.replaceChild(新节点,旧节点)
		- 使用一个新的节点去替换旧节点
		
	父节点.removeChild(子节点)
		- 删除指定的子节点
		- 推荐方式:子节点.parentNode.removeChild(子节点)
		

innerHTML 配合 字符串 也可以完成上述操作,但浏览器在添加元素时,会把之前存在的相同的元素节点覆盖替换,比较浪费资源,须在合适的时机使用

    myClick('btn02', function () {
        var li = document.createElement('li')
        // var text = document.createTextNode('广州')
        // li.appendChild(text);
        li.innerHTML = '广州'
        city.insertBefore(li, bj)
    })

6.文档的加载

	- 文档的加载
		- 浏览器在加载一个页面时,是按照自上向下的顺序加载的,加载一行执行一行。
		- 如果将js代码编写到页面的上边,当代码执行时,页面中的DOM对象还没有加载,
			此时将会无法正常获取到DOM对象,导致DOM操作失败。
		- 解决方式一:
			- 可以将js代码编写到body的下边
			<body>
				<button id="btn">按钮</button>
				<script>
					var btn = document.getElementById("btn");
					btn.onclick = function(){
					
					};
				</script>
			</body>
			
		- 解决方式二:
			- 将js代码编写到window.onload = function(){}中
			- window.onload 对应的回调函数会在整个页面加载完毕以后才执行,
				所以可以确保代码执行时,DOM对象已经加载完毕了
			<script>
				window.onload = function(){
					var btn = document.getElementById("btn");
					btn.onclick = function(){
					
					};
				};
			
			</script>	

7.DOMCSS的操作

DOM对CSS的操作
	- 读取和修改内联样式
		- 使用style属性来操作元素的内联样式
		- 读取内联样式:
			语法:元素.style.样式名
			- 例子:
				元素.style.width
				元素.style.height
				- 注意:如果样式名中带有-,则需要将样式名修改为驼峰命名法
					将-去掉,然后-后的字母改大写
				- 比如:background-color --> backgroundColor
						border-width ---> borderWidth
						
		- 修改内联样式:
			语法:元素.style.样式名 = 样式值(为字符串)
			- 通过style修改的样式都是内联样式,由于内联样式的优先级比较高,
				所以我们通过JS来修改的样式,往往会立即生效,
				但是如果样式中设置了!important,则内联样式将不会生效。
				
	- 读取元素的当前样式
		- 正常浏览器
			- 使用getComputedStyle()
			- 这个方法是window对象的方法,可以返回一个对象,这个对象中保存着当前元素生效样式
			- 参数:
				1.要获取样式的元素
				2.可以传递一个伪元素,一般传null
			- 例子:
				获取元素的宽度
					getComputedStyle(box , null)["width"];
			- 通过该方法读取到样式都是只读的不能修改

		- IE8
			- 使用currentStyle
			- 语法:
				元素.currentStyle.样式名
			- 例子:
				box.currentStyle["width"] (不好的地方 div宽度可能读到auto)
			- 通过这个属性读取到的样式是只读的不能修改
			
			读取当前样式兼容写法
		function getStyle(obj , name){
			
			if(window.getComputedStyle){
				//正常浏览器的方式,具有getComputedStyle()方法
				return getComputedStyle(obj , null)[name];
			}else{
				//IE8的方式,没有getComputedStyle()方法
				return obj.currentStyle[name];
			}
			
			//return window.getComputedStyle?getComputedStyle(obj , null)[name]:obj.currentStyle[name];
			
		}
		```
- 其他的样式相关的属性
	注意:以下样式都是只读的

	clientHeight
		- 元素的可见高度,指元素的-内容区和内边距-的高度
	clientWidth
		- 元素的可见宽度,指元素的-内容区和内边距-的宽度
	offsetHeight
		- 整个元素的高度,包括-内容区、内边距、边框-
	offsetWidth
		- 整个元素的宽度,包括-内容区、内边距、边框-
	offsetParent
		- 当前元素的定位父元素
		- 离他最近的开启了定位的祖先元素,如果所有的元素都没有开启定位,则返回body
	offsetLeft
	offsetTop
		- 当前元素和定位父元素之间的偏移量
		- offsetLeft水平偏移量  offsetTop垂直偏移量
	
	scrollHeight
	scrollWidth
		- 获取元素滚动区域的高度和宽度  -内容区和内边距-
	
	scrollTop
	scrollLeft
		- 获取元素垂直和水平滚动条滚动的距离
		
	判断滚动条是否滚动到底
		- 垂直滚动条
			scrollHeight - scrollTop = clientHeight
			
		- 水平滚动	
			scrollWidth - scrollLeft = clientWidth

			//当满足scrollHeight - scrollTop == clientHeight
			//说明垂直滚动条滚动到底了

			//当满足scrollWidth - scrollLeft == clientWidth
			//说明水平滚动条滚动到底

8.对类的操作

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style type="text/css">
			
			.b1{
				width: 100px;
				height: 100px;
				background-color: red;
			}
			
			.b2{
				height: 300px;
				background-color: yellow;
			}
			
		</style>
		
		<script type="text/javascript">
			
			window.onload = function(){
				//获取box
				var box = document.getElementById("box");
				//获取btn01
				var btn01 = document.getElementById("btn01");
				
				//为btn01绑定单击响应函数
				btn01.onclick = function(){
					//修改box的样式
					/*
					 * 通过style属性来修改元素的样式,每修改一个样式,浏览器就需要重新渲染一次页面
					 * 	这样的执行的性能是比较差的,而且这种形式当我们要修改多个样式时,也不太方便
					 */
					/*box.style.width = "200px";
					box.style.height = "200px";
					box.style.backgroundColor = "yellow";*/
					
					/*
					 * 我希望一行代码,可以同时修改多个样式
					 */
					
					//修改box的class属性
					/*
					 * 我们可以通过修改元素的class属性来间接的修改样式
					 * 这样一来,我们只需要修改一次,即可同时修改多个样式,
					 * 	浏览器只需要重新渲染页面一次,性能比较好,
					 * 	并且这种方式,可以使表现和行为进一步的分离
					 */
					//box.className += " b2";
					//addClass(box,"b2");
					
					//alert(hasClass(box,"hello"));
					
					//removeClass(box,"b2");
					
					toggleClass(box,"b2");
				};
				
			};
			
			//定义一个函数,用来向一个元素中添加指定的class属性值
			/*
			 * 参数:
			 * 	obj 要添加class属性的元素
			 *  cn 要添加的class值
			 * 	
			 */
			function addClass(obj , cn){
				
				//检查obj中是否含有cn
				if(!hasClass(obj , cn)){
					obj.className += " "+cn;
				}
				
			}
			
			/*
			 * 判断一个元素中是否含有指定的class属性值
			 * 	如果有该class,则返回true,没有则返回false
			 * 	
			 */
			function hasClass(obj , cn){
				
				//判断obj中有没有cn class
				//创建一个正则表达式
				//var reg = /\bb2\b/;
				var reg = new RegExp("\\b"+cn+"\\b");
				
				return reg.test(obj.className);
				
			}
			
			/*
			 * 删除一个元素中的指定的class属性
			 */
			function removeClass(obj , cn){
				//创建一个正则表达式
				var reg = new RegExp("\\b"+cn+"\\b");
				
				//删除class
				obj.className = obj.className.replace(reg , "");
				
			}
			
			/*
			 * toggleClass可以用来切换一个类
			 * 	如果元素中具有该类,则删除
			 * 	如果元素中没有该类,则添加
			 */
			function toggleClass(obj , cn){
				
				//判断obj中是否含有cn
				if(hasClass(obj , cn)){
					//有,则删除
					removeClass(obj , cn);
				}else{
					//没有,则添加
					addClass(obj , cn);
				}
				
			}
			
		</script>
	</head>
	<body>
		
		<button id="btn01">点击按钮以后修改box的样式</button>
		
		<br/><br />
		
		<div id="box" class="b1 b2"></div>
	</body>
</html>

四、事件(Event)

1.了解 事件

  • 指的就是用户与浏览器交互的一瞬间
  • 我们通过为指定事件绑定回调函数的形式来处理事件,当指定事件触发以后我们的回调函数就会被调用,这样我们的页面就可以完成和用户的交互了。
	- 事件(Event)
		- 事件指的是用户和浏览器之间的交互行为。比如:点击按钮、关闭窗口、鼠标移动。。。
		- 我们可以为事件来绑定回调函数来响应事件。
		- 绑定事件的方式:
			1.可以在标签的事件属性中设置相应的JS代码
				例子:
					<button οnclick="js代码。。。">按钮</button>
			2.可以通过为对象的指定事件属性设置回调函数的形式来处理事件
				例子:
					<button id="btn">按钮</button>
					<script>
						var btn = document.getElementById("btn");
						btn.onclick = function(){
						
						};
					</script>

2.事件处理程序

  • 我们可以通过两种方式为一个元素绑定事件处理程序:

    – 通过HTML元素指定事件属性来绑定

    – 通过DOM对象指定的属性来绑定

  • 这两种方式都是我们日常用的比较多的,但是更推荐使用第二种方式。

  • 还有一种方式比较特殊我们称为设置事件监听器。使用如下方式:

    元素对象.addEventListener()

3.通过HTML标签的属性设置

  • 通过HTML属性来绑定事件处理程序是最简单的方式。
<button onclick="alert('hello');alert('world')">按钮</button>
  • 这种方式当我们点击按钮以后,onclick属性中对应的JS代码将会执行,也就是点击按钮以后,页面中会弹出两个提示框。

  • 这种方式我们直接将代码编写到了onclick属性中,可以编写多行js代码,当然也可以事先在外部定义好函数。

  • 这种方式的优点在于,设定步骤非常简单,并且能够确保事件处理程序会在载入时被设定。

  • 如果在函数的最后return false则会取消元素的默认行为。

  • * 使用addEventListener()方法绑定响应函数,取消默认行为时不能使用return false
    * 需要使用event来取消默认行为event.preventDefault();
    * 但是IE8不支持event.preventDefault();这个玩意,如果直接调用会报错
    
  • <a href="javascript:;">Delete</a>可以取消啊的默认行为

4.通过DOM对象的属性绑定

  • 但是其实上面的写法虽然简单,但却将JSHTML的代码编写到了一起,并不推荐使用,我们更推荐

如下的写法:

var btn = document.getElementById('btn');
btn.onclick = function(){
	alert("hello");
};
  • 这种写法将HTML代码和JS写在不同的位置,维护起来更加容易。

5.设置事件监听器

  • 前边两种方式都可以绑定事件处理程序,但是它们都有一个缺点就是都只能绑定一个程序,而不能为一个事件绑定多个程序,如果绑定了多个,则后边会覆盖掉前边的。

  • 这是我们就可以使用addEventListener()来处理,这个方法需要三个参数:

    •   1.事件的字符串,不要on
      
    •   2.回调函数,当事件触发时该函数会被调用
      
    •   3.是否在捕获阶段触发事件,需要一个布尔值,一般都传false 默认 false,可以不填
      
    • 使用addEventListener()方法绑定响应函数,取消默认行为时不能使用return false

    • 需要使用event来取消默认行为event.preventDefault();

    • 但是IE8不支持event.preventDefault();这个玩意,如果直接调用会报错

btn.addEventListener('click' , function(){alert("hello");},false);**
  • 但是要注意的是ie8以下的浏览器是不支持上边的方法的,需要使用attachEvent代替。
  • 也可以使用removeEventListener()detachEvent()移除事件。
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<script type="text/javascript">
			
			window.onload = function(){
				
				/*
				 * 点击按钮以后弹出一个内容
				 */
				//获取按钮对象
				var btn01 = document.getElementById("btn01");
				
				/*
				 * 使用 对象.事件 = 函数 的形式绑定响应函数,
				 * 	它只能同时为一个元素的一个事件绑定一个响应函数,
				 * 	不能绑定多个,如果绑定了多个,则后边会覆盖掉前边的
				 */
				
				//为btn01绑定一个单击响应函数
				/*btn01.onclick = function(){
					alert(1);
				};*/
				
				//为btn01绑定第二个响应函数
				/*btn01.onclick = function(){
					alert(2);
				};*/
				
				/*
				 * addEventListener()
				 * 	- 通过这个方法也可以为元素绑定响应函数
				 *  - 参数:
				 * 		1.事件的字符串,不要on
				 * 		2.回调函数,当事件触发时该函数会被调用
				 * 		3.是否在捕获阶段触发事件,需要一个布尔值,一般都传false
				 * 
				 * 使用addEventListener()可以同时为一个元素的相同事件同时绑定多个响应函数,
				 * 	这样当事件被触发时,响应函数将会按照函数的绑定顺序执行
				 * 
				 * 这个方法不支持IE8及以下的浏览器
				 */
				/*btn01.addEventListener("click",function(){
					alert(1);
				},false);
				
				btn01.addEventListener("click",function(){
					alert(2);
				},false);
				
				btn01.addEventListener("click",function(){
					alert(3);
				},false);*/
				
				/*
				 * attachEvent()
				 * 	- 在IE8中可以使用attachEvent()来绑定事件
				 *  - 参数:
				 * 		1.事件的字符串,要on
				 * 		2.回调函数
				 * 
				 *  - 这个方法也可以同时为一个事件绑定多个处理函数,
				 * 		不同的是它是后绑定先执行,执行顺序和addEventListener()相反
				 */
				/*btn01.attachEvent("onclick",function(){
					alert(1);
				});
				
				btn01.attachEvent("onclick",function(){
					alert(2);
				});
				
				btn01.attachEvent("onclick",function(){
					alert(3);
				});*/
				
				/*btn01.addEventListener("click",function(){
					alert(this);
				},false);*/
				
				/*btn01.attachEvent("onclick",function(){
					alert(this);
				});*/
				
				bind(btn01 , "click" , function(){
					alert(this);
				});
			
				
			};
			
			//定义一个函数,用来为指定元素绑定响应函数
			/*
			 * addEventListener()中的this,是绑定事件的对象
			 * attachEvent()中的this,是window
			 *  需要统一两个方法this
			 */
			/*
			 * 参数:
			 * 	obj 要绑定事件的对象
			 * 	eventStr 事件的字符串(不要on)
			 *  callback 回调函数
			 */
			function bind(obj , eventStr , callback){
				if(obj.addEventListener){
					//大部分浏览器兼容的方式
					obj.addEventListener(eventStr , callback , false);
				}else{
					/*
					 * this是谁由调用方式决定
					 * callback.call(obj)
					 */
					//IE8及以下
					obj.attachEvent("on"+eventStr , function(){
						//在匿名函数中调用回调函数
						callback.call(obj);
					});
				}
			}
			
		</script>
	</head>
	<body>
		
		<button id="btn01">点我一下</button>
	</body>
</html>

6.事件处理中的this

  • 事件处理程序内的 this 所引用的对象即是设定了该事件处理程序的元素(IE的’attachEvent '里的this是window)。
  • 也就是事件是给那个对象绑定的this就是哪个对象。
  • 再循环中事件处理的回调函数多使用this ,慎用 for循环的index ,回调函数执行时,index已成为定值(循环结束后的值,不能如愿的根据index索引到指定元素删除),即使用的是let 定义的index ,也要慎用,尤其回调函数中有添加删除此类元素节点的操作

image-20220224194306969

7.事件对象

  • 在DOM对象上的某个事件被触发时,会产生一个事件对象Event,这个对象中包含着所有事件有关的信息。包括导致事件的元素、事件的类型以及其他与特定事件相关的信息

  • 例如,鼠标操作导致的事件对象中,会包含鼠标位置的信息,而键盘操作导致的事件对象中,会包含与按下的键有关的信息。所有浏览器都支持 event 对象,但支持方式不同。

  • DOM标准的浏览器会将一个event对象传入到事件的处理程序当中。无论事件处理程序是什么都会传入一个event对象。

  • 可以通过这种方式获取:

btn.onclick = function(event){
	alert(event.type);
};
  • Event对象包含与创建它的特定事件有关的属性和方法。触发的事件类型不一样,可用的属性和方法也不一样。

Event对象的通用属性/方法

image-20220223233814412

8.IE中的事件对象

  • 与访问 DOM 中的 event 对象不同,要访问 IE 中 的 event 对象有几种不同的方式,取决于指定事件处理程序的方法。

  • 在IE中event对象作为window对象的属性存在的,可以使用window.event来获取event对象。

  • 在使用attachEvent()的情况下,也会在处理程序中传递一个event对象,也可以按照前边的方式使用。

Event对象的通用属性/方法(IE)

image-20220223233843102

事件
	- 事件对象
	- 当响应函数被调用时,浏览器每次都会将一个事件对象作为实参传递进响应函数中,
		这个事件对象中封装了当前事件的相关信息,比如:鼠标的坐标,键盘的按键,鼠标的按键,滚轮的方向。。
	- 可以在响应函数中定义一个形参,来使用事件对象,但是在IE8以下浏览器中事件对象没有做完实参传递,而是作为window对象的属性保存
		- 例子:
			元素.事件 = function(event){
				event = event || window.event;
				
			};
			
			元素.事件 = function(e){
				e = e || event;
				
			};

9.事件的触发

  • 事件的发生主要是由用户操作引起的。

  • 比如mousemove这个事件就是由于用户移动鼠标引起的,在鼠标指针移动的过程中该事件会持续发生。

  • 当指定事件被触发时,浏览器就会调用对应的函数去响应事件,一般情况下事件没触发一次,函数就会执行一次。

  • 因此设置鼠标移动的事件可能会影响到鼠标的移动速度。所以设置该类事件时一定要谨慎。

10.事件的传播

  • 在网页中标签与标签之间是有嵌套关系的,比如这样一个页面:

    <html>
        <body>
            <div id="foo">
                <button id="bar">sample</button>
            </div>
        </body>
    </html>
    
  • 如果这时用户点击了sample按钮,则会以该按钮作为事件目标触发一次点击事件。

  • 这时,事件的处理将会分为捕获阶段、目标阶段、事件冒泡这三个阶段。

事件的传播流程

image-20220223233922749

  • 捕获阶段

    – 这一阶段会从window对象开始向下一直遍历到目标对象,如果发现有对象绑定了响应事件则做相应的处理。

  • 目标阶段

    – 这一阶段已经遍历结束,则会执行目标对象上绑定的响应函数。

  • 事件冒泡阶段

    – 这一阶段,事件的传播方式和捕获阶段正好相反,会从事件目标一直向上遍历,直至window对象结束,这时对象上绑定的响应函数也会执行。

取消事件传播

  • 我们可以使用event对象的两个方法完成:

    stopPropagation():取消事件的进一步捕获或冒泡

    stopImmediatePropagation():取消事件的进一步捕获或冒泡

  • 取消默认行为:

    preventDefault()

	- 事件的冒泡(Bubble)
	- 事件的冒泡指的是事件向上传导,当后代元素上的事件被触发时,将会导致其祖先元素上的同类事件也会触发。
	- 事件的冒泡大部分情况下都是有益的,如果需要取消冒泡,则需要使用事件对象来取消
	- 可以将事件对象的cancelBubble设置为true,即可取消冒泡
		- 例子:
				元素.事件 = function(event){
					event = event || window.event;
					event.cancelBubble = true;
				};

11.常用的事件属性

MouseEvent - WheelEvent 继承MouseEvent

WheelEvent 只有事件wheel属于这个对象

属性/方法描述
clientX返回触发鼠标事件时,鼠标指针相对于当前窗口的水平坐标。
clientY返回触发鼠标事件时,鼠标指针相对于当前窗口的垂直坐标。
offsetX返回鼠标指针相对于目标元素边缘位置的水平坐标。
offsetY返回鼠标指针相对于目标元素边缘位置的垂直坐标。
pageX返回触发鼠标事件时鼠标指针相对于文档的水平坐标。
pageY返回触发鼠标事件时鼠标指针相对于文档的垂直坐标。
screenX返回触发事件时鼠标指针相对于屏幕的水平坐标。
screenY返回触发事件时鼠标指针相对于屏幕的垂直坐标。
注意
chrome的html无法触发onscroll事件,离谱的是chrome的html可以读取scrollTop属性,但是chrome的body不能读取
触发事件建议直接使用  document.onscroll
读取 scrollTop 使用 如下表达式
	document.body.scrollTop || document.documentElement.scrollTop;

KeyboardEvent

这些事件类型属于 KeyboardEvent 对象:

事件描述
onkeydown当用户正在按下键时,发生此事件。
onkeypress当用户按了某个键时,发生此事件。
onkeyup当用户松开键时,发生此事件。
属性/方法描述
altKey返回触发按键事件时是否按下了 “ALT” 键。
charCode返回触发 onkeypress 事件的键的 Unicode 字符代码。
code返回触发事件的键的代码。
ctrlKey返回按键鼠标事件时是否按下了 “CTRL” 键。
getModifierState()如果指定的键被激活,则返回 true。
isComposing返回事件的状态是否正在构成。
key返回事件表示的键的键值。
keyCode返回触发 onkeypress 事件的键的 Unicode 字符码,或触发 onkeydown 或 onkeyup 事件的键的 Unicode 键码。
location返回键盘或设备上按键的位置。
metaKey返回按键事件触发时是否按下了 “META” 键。
repeat返回是否重复按住某个键。
shiftKey返回按键事件触发时是否按下了 “SHIFT” 键。
which返回触发 onkeypress 事件的键的 Unicode 字符码,或触发 onkeydownonkeyup 事件的键的 Unicode 键码

12.事件的委派

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script type="text/javascript">
			
			window.onload = function(){
				
				var u1 = document.getElementById("u1");
				
				//点击按钮以后添加超链接
				var btn01 = document.getElementById("btn01");
				btn01.onclick = function(){
					//创建一个li
					var li = document.createElement("li");
					li.innerHTML = "<a href='javascript:;' class='link'>新建的超链接</a>";
					
					//将li添加到ul中
					u1.appendChild(li);
				};
				
				
				/*
				 * 为每一个超链接都绑定一个单击响应函数
				 * 这里我们为每一个超链接都绑定了一个单击响应函数,这种操作比较麻烦,
				 * 	而且这些操作只能为已有的超链接设置事件,而新添加的超链接必须重新绑定
				 */
				//获取所有的a
				var allA = document.getElementsByTagName("a");
				//遍历
				/*for(var i=0 ; i<allA.length ; i++){
					allA[i].onclick = function(){
						alert("我是a的单击响应函数!!!");
					};
				}*/
				
				/*
				 * 我们希望,只绑定一次事件,即可应用到多个的元素上,即使元素是后添加的
				 * 我们可以尝试将其绑定给元素的共同的祖先元素
				 * 
				 * 事件的委派
				 * 	- 指将事件统一绑定给元素的共同的祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素
				 * 		从而通过祖先元素的响应函数来处理事件。
				 *  - 事件委派是利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能
				 */
				
				//为ul绑定一个单击响应函数
				u1.onclick = function(event){
					event = event || window.event;
					
					/*
					 * target
					 * 	- event中的target表示的触发事件的对象
					 */
					//alert(event.target);
					
					
					//如果触发事件的对象是我们期望的元素,则执行否则不执行
                    //
					if(/\blink\b/.test(event.target.className){
						alert("我是ul的单击响应函数");
					}
					
				};
				
			};
			
		</script>
	</head>
	<body>
		<button id="btn01">添加超链接</button>
		
		<ul id="u1" style="background-color: #bfa;">
			<li>
				<p>我是p元素</p>
			</li>
			<li><a href="javascript:;" class="link">超链接一</a></li>
			<li><a href="javascript:;" class="link">超链接二</a></li>
			<li><a href="javascript:;" class="link">超链接三</a></li>
		</ul>
		
	</body>
</html>

13.案例

1).拖拽

取消浏览器鼠标默认行为
return false

IE:
设置某元素捕获所有鼠标按下的事件
* 一次性的
* setCapture()
* 	- 只有IE支持,但是在火狐中调用时不会报错,
* 		而如果使用chrome调用,会报错
取消某元素捕获所有鼠标按下的事件
* releaseCapture();
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        #box1 {
            width: 100px;
            height: 100px;
            background-color: red;
            position: absolute;
        }

        #box2 {
            width: 100px;
            height: 100px;
            background-color: yellow;
            position: absolute;

            left: 200px;
            top: 200px;
        }
    </style>

    <script type="text/javascript">

        window.onload = function () {
            /*
             * 拖拽box1元素
             *  - 拖拽的流程
             * 		1.当鼠标在被拖拽元素上按下时,开始拖拽  onmousedown
             * 		2.当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
             * 		3.当鼠标松开时,被拖拽元素固定在当前位置	onmouseup
             */

            //获取box1
            var box1 = document.getElementById("box1");
            var box2 = document.getElementById("box2");
            var img1 = document.getElementById("img1");
            drag(box1)
            drag(box2)
            drag(img1)
        };


        function drag(obj) {


            obj.onmousedown = function () {
                //设置box1捕获所有鼠标按下的事件
                /*
                 * setCapture()
                 * 	- 只有IE支持,但是在火狐中调用时不会报错,
                 * 		而如果使用chrome调用,会报错
                 */
                /*if(box1.setCapture){
                    box1.setCapture();
                }*/
                box1.setCapture && box1.setCapture();


                var ol = event.offsetX;
                var ot = event.offsetY;
                document.onmousemove = function (event) {

                    obj.style.left = event.clientX - ol + "px";
                    obj.style.top = event.clientY - ot + "px";
                }
                document.onmouseup = function () {
                    document.onmousemove = null
                    document.onmouseup = null


                    obj.releaseCapture && obj.releaseCapture();
                }

                /*
                *   当我们拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,
                * 	此时会导致拖拽功能的异常,这个是浏览器提供的默认行为,
                * 	如果不希望发生这个行为,则可以通过return false来取消默认行为
                * 
                *   但是这招对IE8不起作用
                */
                return false
            }


        }


    </script>
</head>

<body>

    我是一段文字

    <div id="box1"></div>

    <div id="box2"></div>


</body>

</html>

2).滚轮事件

* 使用addEventListener()方法绑定响应函数,取消默认行为时不能使用return false
* 需要使用event来取消默认行为event.preventDefault();
* 但是IE8不支持event.preventDefault();这个玩意,如果直接调用会报错
<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8">
	<title></title>
	<style type="text/css">
		#box1 {
			width: 100px;
			height: 100px;
			background-color: red;
		}
	</style>
	<script type="text/javascript">

		window.onload = function () {


			//获取id为box1的div
			var box1 = document.getElementById("box1");

			//为box1绑定一个鼠标滚轮滚动的事件
			/*
			 * onmousewheel鼠标滚轮滚动的事件,会在滚轮滚动时触发,
			 * 	但是火狐不支持该属性
			 * 
			 * 在火狐中需要使用 DOMMouseScroll 来绑定滚动事件
			 * 	注意该事件需要通过addEventListener()函数来绑定
			 */


			box1.onmousewheel = function (event) {

				event = event || window.event;


				//event.wheelDelta 可以获取鼠标滚轮滚动的方向
				//向上滚 120   向下滚 -120
				//wheelDelta这个值我们不看大小,只看正负

				//alert(event.wheelDelta);

				//wheelDelta这个属性火狐中不支持
				//在火狐中使用event.detail来获取滚动的方向
				//向上滚 -3  向下滚 3
				//alert(event.detail);


				/*
				 * 当鼠标滚轮向下滚动时,box1变长
				 * 	当滚轮向上滚动时,box1变短
				 */
				//判断鼠标滚轮滚动的方向
				if (event.wheelDelta > 0 || event.detail < 0) {
					//向上滚,box1变短
					box1.style.height = box1.clientHeight - 10 + "px";

				} else {
					//向下滚,box1变长
					box1.style.height = box1.clientHeight + 10 + "px";
				}

				/*
				 * 使用addEventListener()方法绑定响应函数,取消默认行为时不能使用return false
				 * 需要使用event来取消默认行为event.preventDefault();
				 * 但是IE8不支持event.preventDefault();这个玩意,如果直接调用会报错
				 */
				event.preventDefault && event.preventDefault();


				/*
				 * 当滚轮滚动时,如果浏览器有滚动条,滚动条会随之滚动,
				 * 这是浏览器的默认行为,如果不希望发生,则可以取消默认行为
				 */
				return false;




			};

			//为火狐绑定滚轮事件
			bind(box1, "DOMMouseScroll", box1.onmousewheel);


		};


		function bind(obj, eventStr, callback) {
			if (obj.addEventListener) {
				//大部分浏览器兼容的方式
				obj.addEventListener(eventStr, callback, false);
			} else {
				/*
				 * this是谁由调用方式决定
				 * callback.call(obj)
				 */
				//IE8及以下
				obj.attachEvent("on" + eventStr, function () {
					//在匿名函数中调用回调函数
					callback.call(obj);
				});
			}
		}

	</script>
</head>

<body style="height: 2000px;">

	<div id="box1"></div>

</body>

</html>

3).键盘事件

/*
* 键盘事件:
* 	onkeydown
* 		- 按键被按下
* 		- 对于onkeydown来说如果一直按着某个按键不松手,则事件会一直触发
* 		- 当onkeydown连续触发时,第一次和第二次之间会间隔稍微长一点,其他的会非常的快
* 			这种设计是为了防止误操作的发生。
*       - keycode无法区分大小写
* 	onkeyup
* 		- 按键被松开
*       - keycode可以区分大小写
*   onkeypress 与onkeydown类似 ,但是无法监测功能键和和功能组合键
* 
*  键盘事件一般都会绑定给一些可以获取到焦点的对象或者是document
*/

/*
* 可以通过keyCode来获取按键的编码
* 	通过它可以判断哪个按键被按下
* 除了keyCode,事件对象中还提供了几个属性
* 	altKey
* 	ctrlKey
* 	shiftKey
* 		- 这个三个用来判断alt ctrl 和 shift是否被按下
* 			如果按下则返回true,否则返回false
*/

//如果在onkeydown中取消了默认行为,则输入的内容,不会出现在文本框中
return false 

//在文本框中输入内容,属于onkeydown的默认行为
//如果在onkeydown中取消了默认行为,则输入的内容,不会出现在文本框中

按键移动div

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style type="text/css">
			#box1{
				width: 100px;
				height: 100px;
				background-color: red;
				position: absolute;
			}
			
			
		</style>
		
		<script type="text/javascript">
			
			//使div可以根据不同的方向键向不同的方向移动
			/*
			 * 按左键,div向左移
			 * 按右键,div向右移
			 * 。。。
			 */
			window.onload = function(){
				
				//为document绑定一个按键按下的事件
				document.onkeydown = function(event){
					event = event || window.event;
					
					//定义一个变量,来表示移动的速度
					var speed = 10;
					
					//当用户按了ctrl以后,速度加快
					if(event.ctrlKey){
						speed = 500;
					}
					
					/*
					 * 37 左
					 * 38 上
					 * 39 右
					 * 40 下
					 */
					switch(event.keyCode){
						case 37:
							//alert("向左"); left值减小
							box1.style.left = box1.offsetLeft - speed + "px";
							break;
						case 39:
							//alert("向右");
							box1.style.left = box1.offsetLeft + speed + "px";
							break;
						case 38:
							//alert("向上");
							box1.style.top = box1.offsetTop - speed + "px";
							break;
						case 40:
							//alert("向下");
							box1.style.top = box1.offsetTop + speed + "px";
							break;
					}
					
				};
				
			};
			
			
		</script>
	</head>
	<body>
		<div id="box1"></div>
	</body>
</html>

五、BOM

1.什么是BOM

  • ECMAScript无疑是JavaScript的核心,但是要想在浏览器中使用JavaScript,那么BOM(浏览器对象模型)才是真正的核心。
  • BOM 提供了很多对象,用于访问浏览器的功能,这些功能与任何网页内容无关。
  • BOM将浏览器中的各个部分转换成了一个一个的对象,我们通过修改这些对象的属性,调用他们的方法,从而控制浏览器的各种行为。
/*
* BOM
* 	- 浏览器对象模型
* 	- BOM可以使我们通过JS来操作浏览器
* 	- 在BOM中为我们提供了一组对象,用来完成对浏览器的操作
* 	- BOM对象
* 		Window
* 			- 代表的是整个浏览器的窗口,同时window也是网页中的全局对象
* 		Navigator
* 			- 代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器
* 		Location
* 			- 代表当前浏览器的地址栏信息,通过Location可以获取地址栏信息,或者操作浏览器跳转页面
* 		History
* 			- 代表浏览器的历史记录,可以通过该对象来操作浏览器的历史记录
* 				由于隐私原因,该对象不能获取到具体的历史记录,只能操作浏览器向前或向后翻页
* 				**而且该操作只在当次访问时有效**
* 		Screen
* 			- 代表用户的屏幕的信息,通过该对象可以获取到用户的显示器的相关的信息
* 
* 
* 		这些BOM对象在浏览器中都是作为window对象的属性保存的,
* 			可以通过window对象来使用,也可以直接使用
* 
* 		
*/

2.window对象

  • window对象是BOM的核心,它表示一个浏览器的实例。

  • 在浏览器中我们可以通过window对象来访问操作浏览器,同时window也是作为全局对象存在的。

  • 全局作用域:

    – window对象是浏览器中的全局对象,因此所有在全局作用域中声明的变量、对象、函数都会变成window对象的属性和方法。

3.窗口大小

  • 浏览器中提供了四个属性用来确定窗口大小:

    – 网页窗口的大小

    • innerWidth
    • innerHeight

    – 浏览器本身的尺寸

    • outerWidth
    • outerHeight

4.打开窗口

  • 使用 window.open()方法既可以导航到一个特定的 URL,也可以打开一个新的浏览器窗口。

  • 这个方法需要四个参数:

    – 需要加载的url地址

    – 窗口的目标

    – 一个特性的字符串

    – 是否创建新的历史记录

5.超时调用

  • 超时调用:

    setTimeout()

    – 超过一定时间以后执行指定函数

    – 需要连个参数:

    • 要执行的内容
    • 超过的时间
  • 取消超时调用

    clearTimeout()

  • 超时调用都是在全局作用域中执行的。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<script type="text/javascript">
			
			var num = 1;
			
			//开启一个定时器
			/*setInterval(function(){
				console.log(num++);
			},3000);*/
			
			
			/*
			 * 延时调用,
			 * 	延时调用一个函数不马上执行,而是隔一段时间以后在执行,而且只会执行一次
			 * 
			 * 延时调用和定时调用的区别,定时调用会执行多次,而延时调用只会执行一次
			 * 
			 * 延时调用和定时调用实际上是可以互相代替的,在开发中可以根据自己需要去选择
			 */
			var timer = setTimeout(function(){
				console.log(num++);
			},3000);
			
			//使用clearTimeout()来关闭一个延时调用
			clearTimeout(timer);
			
		</script>
	</head>
	<body>
	</body>
</html>

6.间歇调用

  • 间歇调用:

    setInterval()

    – 每隔一段时间执行指定代码

    – 在开启定时器之前,需要将当前元素上的其他定时器关闭

    – 需要两个参数:

    • 要执行的代码

    • 间隔的时间

  • 取消间隔调用:

    clearInterval()

    clearInterval()可以接收任意参数,

    如果参数是一个有效的定时器的标识,则停止对应的定时器

    如果参数不是一个有效的标识,则什么也不做

<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8">
	<title></title>
	<script type="text/javascript">

		window.onload = function () {

			console.log(innerWidth);
			console.log(innerHeight);
			console.log(outerWidth);
			console.log(outerHeight);
			//获取count
			var count = document.getElementById("count");

			//使count中的内容,自动切换
			/*
			 * JS的程序的执行速度是非常非常快的
			 * 	如果希望一段程序,可以每间隔一段时间执行一次,可以使用定时调用
			 */
			/*for(var i=0 ; i<10000 ; i++){
				count.innerHTML = i;
				
				alert("hello");
			}*/

			/*
			 * setInterval()
			 * 	- 定时调用
			 * 	- 可以将一个函数,每隔一段时间执行一次
			 * 	- 参数:
			 * 		1.回调函数,该函数会每隔一段时间被调用一次
			 * 		2.每次调用间隔的时间,单位是毫秒
			 * 
			 * 	- 返回值:
			 * 		返回一个Number类型的数据
			 * 		这个数字用来作为定时器的唯一标识
			 */
			var num = 1;

			var timer = setInterval(function () {

				count.innerHTML = num++;

				if (num == 11) {
					//关闭定时器
					clearInterval(timer);
				}

			}, 1000);

			//console.log(timer);

			//clearInterval()可以用来关闭一个定时器
			//方法中需要一个定时器的标识作为参数,这样将关闭标识对应的定时器
			//clearInterval(timer);

		};


	</script>
</head>

<body>
	<h1 id="count"></h1>
</body>

</html>

超时调用和延时调用返回值的类型是number

7.系统对话框

  • 浏览器通过 alert()confirm()prompt() 方法可以调用系统对话框向用户显示消息。

  • 它们的外观由操作系统及(或)浏览器设置决定,而不是由 CSS 决定。

  • 显示系统对话框时会导致程序终止,当关闭对话框程序会恢复执行。

alert

  • alert()接收一个字符串并显示给用户。调用alert()方法会向用户显示一个包含一个确认按钮的对话框。

  • 例如:

    – alert(“Hello World”);

    image-20220224003149097

confirm

  • confirm和alert类似,只不过confirm弹出的对话框有一个确认和取消按钮。用户可以通过按钮来确认是否执行操作。

  • 例如:

    – confirm(‘你确定吗?’);

    image-20220224003229422

  • 这个函数的执行会返回一个布尔值,如果选择确定则返回true,如果点击取消则返回false。

prompt

  • prompt会弹出一个带输入框的提示框,并可以将用户输入的内容返回。

  • 它需要两个值作为参数:

    – 显示的提示文字

    – 文本框中的默认值

  • 例子:

    – prompt(‘你的年龄是?’,‘18’);

    image-20220224003302988

8.location对象

  • location对象提供了与当前窗口中加载的文档有关的信息,还提供了一些导航功能。

  • href属性:

    href属性可以获取或修改当前页面的完整的URL地址,使浏览器跳转到指定页面。

    也可以直接把URL地址直接赋值给location对象

    – 如果直接打印location,则可以获取到地址栏的信息(当前页面的完整路径)

  • assign() 方法

    – 所用和href一样,使浏览器跳转页面,新地址错误参数传递到assign ()方法中

    – 用来跳转到其他的页面,作用和直接修改location一样

  • replace()方法

    – 功能一样,只不过使用replace方法跳转地址不会体现到历史记录中。

  • reload(true) 方法

    – 用于强制刷新当前页面 ,不传参只是刷新页面

<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8">
	<title></title>
	<script type="text/javascript">
		/*
		 * Location
		 * 	- 该对象中封装了浏览器的地址栏的信息
		 */
		window.onload = function () {

			//获取按钮对象
			var btn = document.getElementById("btn");

			btn.onclick = function () {

				//如果直接打印location,则可以获取到地址栏的信息(当前页面的完整路径)
				//alert(location);

				/*
				 * 如果直接将location属性修改为一个完整的路径,或相对路径
				 * 	则我们页面会自动跳转到该路径,并且会生成相应的历史记录
				 */
				//location = "http://www.baidu.com";
				//location = "01.BOM.html";

				/*
				 * assign()
				 * 	- 用来跳转到其他的页面,作用和直接修改location一样
				 */
				//location.assign("http://www.baidu.com");

				/*
				 * reload()
				 * 	- 用于重新加载当前页面,作用和刷新按钮一样
				 * 	- 如果在方法中传递一个true,作为参数,则会强制清空缓存刷新页面
				 *  - chorme 好像自动强制刷新
				 */
				//location.reload(true);

				/*
				 * replace()
				 * 	- 可以使用一个新的页面替换当前页面,调用完毕也会跳转页面
				 * 		不会生成历史记录,不能使用回退按钮回退
				 */
				location.replace("01.BOM.html");

			};

		};

	</script>
</head>

<body>

	<button id="btn">点我一下</button>

	<h1>Location</h1>

	<input type="text" />
	<a href="01.BOM.html">去BOM</a>
</body>

</html>

image-20220313223632083

9.navigator对象

  • navigator 对象包含了浏览器的版本、浏览器所支持的插件、浏览器所使用的语言等各种与浏览器相关的信息。
  • 我们有时会使用navigatoruserAgent属性来检查用户浏览器的版本。
/*
* Navigator
* 	- 代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器
* 	- 由于历史原因,Navigator对象中的大部分属性都已经不能帮助我们识别浏览器了
* 	- 一般我们只会使用userAgent来判断浏览器的信息,
* 		userAgent是一个字符串,这个字符串中包含有用来描述浏览器信息的内容,
* 		不同的浏览器会有不同的userAgent
* 		NT 6.1 win7
*       WOW64:64位系统		Win64; x64
*		Gecko:火狐引擎
*		Firefox:火狐   	Chrome:谷歌
*       
* 火狐的userAgent
* 	Mozilla/5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0
* 
* Chrome的userAgent
*  Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36
* 
* IE8
* 	Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
* 
* IE9
* 	Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
* 
* IE10
* 	Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
* 
* IE11
* 	Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; rv:11.0) like Gecko
* 	- 在IE11中已经将微软和IE相关的标识都已经去除了,所以我们基本已经不能通过UserAgent来识别一个浏览器是否是IE了
*/


		var ua = navigator.userAgent;

		console.log(ua);

		if (/firefox/i.test(ua)) {
			alert("你是火狐!!!");
		} else if (/chrome/i.test(ua)) {
			alert("你是Chrome");
		} else if (/msie/i.test(ua)) {
			alert("你是IE浏览器~~~");
		} else if ("ActiveXObject" in window) {
			alert("你是IE11,枪毙了你~~~");
		}
//ActiveXObject 在IE11 转化为 false ,其他IE 转化为true ,所以用"ActiveXObject" in window

10.screen对象

  • screen 对象基本上只用来表明客户端的能力,其中包括浏览器窗口外部的显示器的信息,如像素宽度和高度等。

  • 该对象作用不大,我们一般不太使用。

11.history对象

  • history 对象保存着用户上网的历史记录,从窗口被打开的那一刻算起。

  • length

    返回浏览器历史列表中的 URL 数量。

  • go()

    – 使用 go() 方法可以在用户的历史记录中任意跳转,可以向后也可以向前。

  • back()

    – 向后跳转

  • forward()

    – 向前跳转

/*
* length
* 	- 属性,可以获取到当成访问的链接数量
*/
//alert(history.length);

/*
* back()
* 	- 可以用来回退到上一个页面,作用和浏览器的回退按钮一样
*/
//history.back();

/*
* forward()
* 	- 可以跳转下一个页面,作用和浏览器的前进按钮一样
*/
//history.forward();

/*
* go()
* 	- 可以用来跳转到指定的页面
* 	- 它需要一个整数作为参数
* 		1:表示向前跳转一个页面 相当于forward()
* 		2:表示向前跳转两个页面
* 		-1:表示向后跳转一个页面
* 		-2:表示向后跳转两个页面
*/

12.document

  • document对象也是window的一个属性,这个对象代表的是整个网页的文档对象。
  • 我们对网页的大部分操作都需要以document对象作为起点。

13.案例

定时器动画效果,利用好回调函数

动画模块 tools.js

//尝试创建一个可以执行简单动画的函数
/*
 * 参数:
 * 	obj:要执行动画的对象
 * 	attr:要执行动画的样式,比如:left top width height
 * 	target:执行动画的目标位置
 * 	speed:移动的速度(正数向右移动,负数向左移动)
 *  callback:回调函数,这个函数将会在动画执行完毕以后执行
 */
function move(obj, attr, target, speed, callback) {
	//关闭上一个定时器
	clearInterval(obj.timer);

	//获取元素目前的位置
	var current = parseInt(getStyle(obj, attr));

	//判断速度的正负值
	//如果从0 向 800移动,则speed为正
	//如果从800向0移动,则speed为负
	if(current > target) {
		//此时速度应为负值
		speed = -speed;
	}

	//开启一个定时器,用来执行动画效果
	//向执行动画的对象中添加一个timer属性,用来保存它自己的定时器的标识
	obj.timer = setInterval(function() {

		//获取box1的原来的left值
		var oldValue = parseInt(getStyle(obj, attr));

		//在旧值的基础上增加
		var newValue = oldValue + speed;

		//判断newValue是否大于800
		//从800 向 0移动
		//向左移动时,需要判断newValue是否小于target
		//向右移动时,需要判断newValue是否大于target
		if((speed < 0 && newValue < target) || (speed > 0 && newValue > target)) {
			newValue = target;
		}

		//将新值设置给box1
		obj.style[attr] = newValue + "px";

		//当元素移动到0px时,使其停止执行动画
		if(newValue == target) {
			//达到目标,关闭定时器
			clearInterval(obj.timer);
			//动画执行完毕,调用回调函数
			callback && callback();
		}

	}, 30);
}

/*
 * 定义一个函数,用来获取指定元素的当前的样式
 * 参数:
 * 		obj 要获取样式的元素
 * 		name 要获取的样式名
 */
function getStyle(obj, name) {

	if(window.getComputedStyle) {
		//正常浏览器的方式,具有getComputedStyle()方法
		return getComputedStyle(obj, null)[name];
	} else {
		//IE8的方式,没有getComputedStyle()方法
		return obj.currentStyle[name];
	}

}

html页面

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        * {
            margin: 0;
            padding: 0;
        }

        #box1 {
            width: 100px;
            height: 100px;
            background-color: red;
            position: absolute;
            left: 0;
        }

        #box2 {
            width: 100px;
            height: 100px;
            background-color: yellow;
            position: absolute;
            left: 0;
            top: 200px;
        }
    </style>
    <script type="text/javascript" src="js/tools.js"></script>
    <script type="text/javascript">

        window.onload = function () {

            //获取box1
            var box1 = document.getElementById("box1");
            //获取btn01
            var btn01 = document.getElementById("btn01");

            //获取btn02
            var btn02 = document.getElementById("btn02");


            //点击按钮以后,使box1向右移动(left值增大)
            btn01.onclick = function () {
                move(box1, "left", 800, 20);
            };


            //点击按钮以后,使box1向左移动(left值减小)
            btn02.onclick = function () {
                move(box1, "left", 0, 10);
            };


            //获取btn03
            var btn03 = document.getElementById("btn03");
            btn03.onclick = function () {
                move(box2, "left", 800, 10);
            };

            //测试按钮
            var btn04 = document.getElementById("btn04");
            btn04.onclick = function () {
                //move(box2 ,"width", 800 , 10);
                //move(box2 ,"top", 800 , 10);
                //move(box2 ,"height", 800 , 10);
                move(box2, "width", 800, 10, function () {
                    move(box2, "height", 400, 10, function () {
                        move(box2, "top", 0, 10, function () {
                            move(box2, "width", 100, 10, function () {

                            });
                        });
                    });
                });
            };
        };

			//定义一个变量,用来保存定时器的标识
        /*
         * 目前我们的定时器的标识由全局变量timer保存,
         * 	所有的执行正在执行的定时器都在这个变量中保存
         */
			//var timer;




    </script>
</head>

<body>

    <button id="btn01">点击按钮以后box1向右移动</button>
    <button id="btn02">点击按钮以后box1向左移动</button>
    <button id="btn03">点击按钮以后box2向右移动</button>
    <button id="btn04">测试按钮</button>

    <br /><br />

    <div id="box1"></div>
    <div id="box2"></div>

    <div style="width: 0; height: 1000px; border-left:1px black solid; position: absolute; left: 800px;top:0;"></div>

</body>

</html>
轮播图

tools.js 与前面的案例相同

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		
		<style type="text/css">
			*{
				margin: 0;
				padding: 0;
			}
			
			/*
			 * 设置outer的样式
			 */
			#outer{
				/*设置宽和高*/
				width: 520px;
				height: 333px;
				/*居中*/
				margin: 50px auto;
				/*设置背景颜色*/
				background-color: greenyellow;
				/*设置padding*/
				padding: 10px 0;
				/*开启相对定位*/
				position: relative;
				/*裁剪溢出的内容*/
				overflow: hidden;
			}
			
			/*设置imgList*/
			#imgList{
				/*去除项目符号*/
				list-style: none;
				/*设置ul的宽度*/
				/*width: 2600px;*/
				/*开启绝对定位*/
				position: absolute;
				/*设置偏移量*/
				/*
				 * 每向左移动520px,就会显示到下一张图片
				 */
				left: 0px;
			}
			
			/*设置图片中的li*/
			#imgList li{
				/*设置浮动*/
				float: left;
				/*设置左右外边距*/
				margin: 0 10px;
			}
			
			/*设置导航按钮*/
			#navDiv{
				/*开启绝对定位*/
				position: absolute;
				/*设置位置*/
				bottom: 15px;
				/*设置left值
				 	outer宽度  520
				 	navDiv宽度 25*5 = 125
				 		520 - 125 = 395/2 = 197.5
				 * */
				/*left: 197px;*/
			}
			
			#navDiv a{
				/*设置超链接浮动*/
				float: left;
				/*设置超链接的宽和高*/
				width: 15px;
				height: 15px;
				/*设置背景颜色*/
				background-color: red;
				/*设置左右外边距*/
				margin: 0 5px;
				/*设置透明*/
				opacity: 0.5;
				/*兼容IE8透明*/
				filter: alpha(opacity=50);
			}
			
			/*设置鼠标移入的效果*/
			#navDiv a:hover{
				background-color: black;
			}
		</style>
		
		<!--引用工具-->
		<script type="text/javascript" src="js/tools.js"></script>
		<script type="text/javascript">
			window.onload = function(){
				//获取imgList
				var imgList = document.getElementById("imgList");
				//获取页面中所有的img标签
				var imgArr = document.getElementsByTagName("img");
				//设置imgList的宽度
				imgList.style.width = 520*imgArr.length+"px";
				
				
				/*设置导航按钮居中*/
				//获取navDiv
				var navDiv = document.getElementById("navDiv");
				//获取outer
				var outer = document.getElementById("outer");
				//设置navDiv的left值
				navDiv.style.left = (outer.offsetWidth - navDiv.offsetWidth)/2 + "px";
				
				//默认显示图片的索引
				var index = 0;
				//获取所有的a
				var allA = document.getElementsByTagName("a");
				//设置默认选中的效果
				allA[index].style.backgroundColor = "black";
				
				/*
				 	点击超链接切换到指定的图片
				 		点击第一个超链接,显示第一个图片
				 		点击第二个超链接,显示第二个图片
				 * */
				
				//为所有的超链接都绑定单击响应函数
				for(var i=0; i<allA.length ; i++){
					
					//为每一个超链接都添加一个num属性
					allA[i].num = i;
					
					//为超链接绑定单击响应函数
					allA[i].onclick = function(){
						
						//关闭自动切换的定时器
						clearInterval(timer);
						//获取点击超链接的索引,并将其设置为index
						index = this.num;
						
						//切换图片
						/*
						 * 第一张  0 0
						 * 第二张  1 -520
						 * 第三张  2 -1040
						 */
						//imgList.style.left = -520*index + "px";
						//设置选中的a
						setA();
						
						//使用move函数来切换图片
						move(imgList , "left" , -520*index , 20 , function(){
							//动画执行完毕,开启自动切换
							autoChange();
						});
						
					};
				}
				
				
				//开启自动切换图片
				autoChange();
				
				
				//创建一个方法用来设置选中的a
				function setA(){
					
					//判断当前索引是否是最后一张图片
					if(index >= imgArr.length - 1){
						//则将index设置为0
						index = 0;
						
						//此时显示的最后一张图片,而最后一张图片和第一张是一摸一样
						//通过CSS将最后一张切换成第一张
						imgList.style.left = 0;
					}
					
					//遍历所有a,并将它们的背景颜色设置为红色
					for(var i=0 ; i<allA.length ; i++){
						allA[i].style.backgroundColor = "";
					}
					
					//将选中的a设置为黑色
					allA[index].style.backgroundColor = "black";
				};
				
				//定义一个自动切换的定时器的标识
				var timer;
				//创建一个函数,用来开启自动切换图片
				function autoChange(){
					
					//开启一个定时器,用来定时去切换图片
					timer = setInterval(function(){
						
						//使索引自增
						index++;
						
						//判断index的值
						index %= imgArr.length;
						
						//执行动画,切换图片
						move(imgList , "left" , -520*index , 20 , function(){
							//修改导航按钮
							setA();
						});
						
					},3000);
					
				}
				
				
			};
			
		</script>
	</head>
	<body>
		<!-- 创建一个外部的div,来作为大的容器 -->
		<div id="outer">
			<!-- 创建一个ul,用于放置图片 -->
			<ul id="imgList">
				<li><img src="img/1.jpg"/></li>
				<li><img src="img/2.jpg"/></li>
				<li><img src="img/3.jpg"/></li>
				<li><img src="img/4.jpg"/></li>
				<li><img src="img/5.jpg"/></li>
				<li><img src="img/1.jpg"/></li>
			</ul>
			<!--创建导航按钮-->
			<div id="navDiv">
				<a href="javascript:;"></a>
				<a href="javascript:;"></a>
				<a href="javascript:;"></a>
				<a href="javascript:;"></a>
				<a href="javascript:;"></a>
			</div>
		</div>
	</body>
</html>
二级菜单

tools.js

//尝试创建一个可以执行简单动画的函数
/*
 * 参数:
 * 	obj:要执行动画的对象
 * 	attr:要执行动画的样式,比如:left top width height
 * 	target:执行动画的目标位置
 * 	speed:移动的速度(正数向右移动,负数向左移动)
 *  callback:回调函数,这个函数将会在动画执行完毕以后执行
 */
function move(obj, attr, target, speed, callback) {
	//关闭上一个定时器
	clearInterval(obj.timer);

	//获取元素目前的位置
	var current = parseInt(getStyle(obj, attr));

	//判断速度的正负值
	//如果从0 向 800移动,则speed为正
	//如果从800向0移动,则speed为负
	if(current > target) {
		//此时速度应为负值
		speed = -speed;
	}

	//开启一个定时器,用来执行动画效果
	//向执行动画的对象中添加一个timer属性,用来保存它自己的定时器的标识
	obj.timer = setInterval(function() {

		//获取box1的原来的left值
		var oldValue = parseInt(getStyle(obj, attr));

		//在旧值的基础上增加
		var newValue = oldValue + speed;

		//判断newValue是否大于800
		//从800 向 0移动
		//向左移动时,需要判断newValue是否小于target
		//向右移动时,需要判断newValue是否大于target
		if((speed < 0 && newValue < target) || (speed > 0 && newValue > target)) {
			newValue = target;
		}

		//将新值设置给box1
		obj.style[attr] = newValue + "px";

		//当元素移动到0px时,使其停止执行动画
		if(newValue == target) {
			//达到目标,关闭定时器
			clearInterval(obj.timer);
			//动画执行完毕,调用回调函数
			callback && callback();
		}

	}, 30);
}

/*
 * 定义一个函数,用来获取指定元素的当前的样式
 * 参数:
 * 		obj 要获取样式的元素
 * 		name 要获取的样式名
 */
function getStyle(obj, name) {

	if(window.getComputedStyle) {
		//正常浏览器的方式,具有getComputedStyle()方法
		return getComputedStyle(obj, null)[name];
	} else {
		//IE8的方式,没有getComputedStyle()方法
		return obj.currentStyle[name];
	}

}

//定义一个函数,用来向一个元素中添加指定的class属性值
/*
 * 参数:
 * 	obj 要添加class属性的元素
 *  cn 要添加的class值
 * 	
 */
function addClass(obj, cn) {

	//检查obj中是否含有cn
	if(!hasClass(obj, cn)) {
		obj.className += " " + cn;
	}

}

/*
 * 判断一个元素中是否含有指定的class属性值
 * 	如果有该class,则返回true,没有则返回false
 * 	
 */
function hasClass(obj, cn) {

	//判断obj中有没有cn class
	//创建一个正则表达式
	//var reg = /\bb2\b/;
	var reg = new RegExp("\\b" + cn + "\\b");

	return reg.test(obj.className);

}

/*
 * 删除一个元素中的指定的class属性
 */
function removeClass(obj, cn) {
	//创建一个正则表达式
	var reg = new RegExp("\\b" + cn + "\\b");

	//删除class
	obj.className = obj.className.replace(reg, "");

}

/*
 * toggleClass可以用来切换一个类
 * 	如果元素中具有该类,则删除
 * 	如果元素中没有该类,则添加
 */
function toggleClass(obj, cn) {

	//判断obj中是否含有cn
	if(hasClass(obj, cn)) {
		//有,则删除
		removeClass(obj, cn);
	} else {
		//没有,则添加
		addClass(obj, cn);
	}

}
<!DOCTYPE html>
<html>

	<head>
		<meta charset="UTF-8">
		<title>二级菜单</title>
		<style type="text/css">
			* {
				margin: 0;
				padding: 0;
				list-style-type: none;
			}
			
			a,img {
				border: 0;
				text-decoration: none;
			}
			
			body {
				font: 12px/180% Arial, Helvetica, sans-serif, "新宋体";
			}
		</style>

		<link rel="stylesheet" type="text/css" href="css/sdmenu.css" />
		
		<script type="text/javascript" src="js/tools.js"></script>
		<script type="text/javascript">
			window.onload = function(){
				
				/*
				 * 我们的每一个菜单都是一个div
				 * 	当div具有collapsed这个类时,div就是折叠的状态
				 * 	当div没有这个类是,div就是展开的状态
				 */
				
				/*
				 * 点击菜单,切换菜单的显示状态
				 */
				//获取所有的class为menuSpan的元素
				var menuSpan = document.querySelectorAll(".menuSpan");
				
				//定义一个变量,来保存当前打开的菜单
				var openDiv = menuSpan[0].parentNode;
				
				//为span绑定单击响应函数
				for(var i=0 ; i<menuSpan.length ; i++){
					menuSpan[i].onclick = function(){
						
						//this代表我当前点击的span
						//获取当前span的父元素
						var parentDiv = this.parentNode;
						
						//切换菜单的显示状态
						toggleMenu(parentDiv);
						
						
						//判断openDiv和parentDiv是否相同
						if(openDiv != parentDiv  && !hasClass(openDiv , "collapsed")){
							//打开菜单以后,应该关闭之前打开的菜单
							//为了可以统一处理动画过渡效果,我们希望在这将addClass改为toggleClass
							//addClass(openDiv , "collapsed");
							//此处toggleClass()不需要有移除的功能
							//toggleClass(openDiv , "collapsed");
							//切换菜单的显示状态
							toggleMenu(openDiv);
						}
						
						//修改openDiv为当前打开的菜单
						openDiv = parentDiv;
						
					};
				}
				
				/*
				 * 用来切换菜单折叠和显示状态
				 */
				function toggleMenu(obj){
					//在切换类之前,获取元素的高度
					var begin = obj.offsetHeight;
					
					//切换parentDiv的显示
					toggleClass(obj , "collapsed");
					
					//在切换类之后获取一个高度
					var end = obj.offsetHeight;
					
					//console.log("begin = "+begin +" , end = "+end);
					//动画效果就是将高度从begin向end过渡
					//将元素的高度重置为begin
					obj.style.height = begin + "px";
					
					//执行动画,从bengin向end过渡
					move(obj,"height",end,10,function(){
						//动画执行完毕,内联样式已经没有存在的意义了,删除之
						obj.style.height = "";
					});
						
				}
				
				
			};
			
			
		</script>
		
	</head>

	<body>

		<div id="my_menu" class="sdmenu">
			<div>
				<span class="menuSpan">在线工具</span>
				<a href="#">图像优化</a>
				<a href="#">收藏夹图标生成器</a>
				<a href="#">邮件</a>
				<a href="#">htaccess密码</a>
				<a href="#">梯度图像</a>
				<a href="#">按钮生成器</a>
			</div>
			<div class="collapsed">
				<span class="menuSpan">支持我们</span>
				<a href="#">推荐我们</a>
				<a href="#">链接我们</a>
				<a href="#">网络资源</a>
			</div>
			<div class="collapsed">
				<span class="menuSpan">合作伙伴</span>
				<a href="#">JavaScript工具包</a>
				<a href="#">CSS驱动</a>
				<a href="#">CodingForums</a>
				<a href="#">CSS例子</a>
			</div>
			<div class="collapsed">
				<span class="menuSpan">测试电流</span>
				<a href="#">Current or not</a>
				<a href="#">Current or not</a>
				<a href="#">Current or not</a>
				<a href="#">Current or not</a>
			</div>
		</div>
	</body>
</html>
举报

相关推荐

0 条评论