javaScript学习笔记【尚硅谷】
这是我在看尚硅谷的前端大神超哥视频时,所记录的笔记!
文章目录
- javaScript学习笔记【尚硅谷】
- @[TOC](文章目录)
- 1、javaScript基本知识
- 1.2、JS编写位置
- 1.3、JS基本语法
- 1.4、变量与字面量
- 1.5、标识符
- 1.6、数据类型
- 1.6.1、Number详解
- 1.6.2、布尔值
- 1.6.3、Null 和undefined
- 1.7、强制类型转换
- 1.7.1、将其他的数据类型转换为String
- 1.7.2、将其他数据类型转换为Number
- 1.7.3、将其他进制转换成布尔类型
- 1.7.4、其他进制的数字
- 拓展:严格检查模式
- 2、算数运算符
- 2.1、一元运算符
- 2.2、自增与自减运算符
- 2.3、逻辑运算符
- 2.3.1、布尔判断
- 2.3.2、非布尔判断
- 2.3.3、判断运算符
- 2.3.4、转义字符
- 2.3.5、相等运算符
- 2..3.6、三目运算符(三元运算符)
- 2.3.7、运算符优先级
- 3、代码块
- 4、流程控制
- 4.1、if语句
- 4.2、switch语句
- 4.3、while循环语句
- 4.4、for循环
- 5、自定义对象
- 5.1、对象的属性
- 拓展章节:基本数据类型与引用数据类型
- 5.2、对象字面量
- 5.3、函数
- 5.3.1、函数的参数
- 5.3.2、函数的返回值
- 5.3.3、匿名函数
- 5.3.4、函数的方法
- 5.4、对象的方法
- 5.5、this(上下文对象)
- 5.6、arguments
- 5.7、工厂动态创对象
- 5.8、构造函数
- 5.8.1、构造函数进阶
- 5.9、原型对象
- 5.10、toString()方法
- 拓展1:枚举对象中的属性
- 拓展2:垃圾回收(GC)
- 拓展3:class关键字
- 6、作用域
- 7、内建对象
- 7.1、数组
- 7.1.1、**length**
- 7.1.2、**数组字面量**
- 7.1.3、**数组中的元素可以是任意数据类型**
- 7.1.4、数组中常用方法
- 7.1.5、数组的遍历
- 7.2、Date对象
- 7.3、Math工具类
- 7.5、包装类
- 7.6、String对象常用方法
- 8、正则表达式
- 8.1、正则表达式字面量方式
- 8.2、字符串&正则表达式
- 8.3、正则表达式语法1
- 8.3、正则表达式语法2
- 9.DOM简介
- 9.1、DOM查询
- 9.1.1基本知识
- 节点
- 节点的属性
- 获取元素节点
- 元素节点的子节点
- 获取父节点和兄弟节点
- 9.1.2、查询剩余属性、方法
- 9.2、DOM删除
- 9.3、操作样式
- 9.3.1、操作内联样式
- 9.3.2、获取元素当前显示样式
- 9.3.3、其他样式操作的属性
- 9.4、事件
- 9.4.1、事件
- 9.4.2、事件对象
- 9.4.3、事件的冒泡
- 9.4.4、事件的委派
- 9.4.5、事件的绑定
- 9.4.6、bind()函数
- 9.4.7、事件的传播
- 9.4.8、拖曳
- 9.4.9、鼠标滚轮事件
- 9.4.10、键盘事件
- 10、BOM简介
- 10.1、Navigator
- 10.2、History
- 10.3、Location
- 10.4、定时器简介
- 10.4.1 定时器练习
- 10.4.2 div随键盘移动·改进
- 10.5、延迟调用
- 10.6、应用
- 10.6.1、定时器的应用
- 10.6.2、轮播图功能实现
- 10.7、类的操作
- 11、JSON
- 完结
文章目录
- javaScript学习笔记【尚硅谷】
- @[TOC](文章目录)
- 1、javaScript基本知识
- 1.2、JS编写位置
- 1.3、JS基本语法
- 1.4、变量与字面量
- 1.5、标识符
- 1.6、数据类型
- 1.6.1、Number详解
- 1.6.2、布尔值
- 1.6.3、Null 和undefined
- 1.7、强制类型转换
- 1.7.1、将其他的数据类型转换为String
- 1.7.2、将其他数据类型转换为Number
- 1.7.3、将其他进制转换成布尔类型
- 1.7.4、其他进制的数字
- 拓展:严格检查模式
- 2、算数运算符
- 2.1、一元运算符
- 2.2、自增与自减运算符
- 2.3、逻辑运算符
- 2.3.1、布尔判断
- 2.3.2、非布尔判断
- 2.3.3、判断运算符
- 2.3.4、转义字符
- 2.3.5、相等运算符
- 2..3.6、三目运算符(三元运算符)
- 2.3.7、运算符优先级
- 3、代码块
- 4、流程控制
- 4.1、if语句
- 4.2、switch语句
- 4.3、while循环语句
- 4.4、for循环
- 5、自定义对象
- 5.1、对象的属性
- 拓展章节:基本数据类型与引用数据类型
- 5.2、对象字面量
- 5.3、函数
- 5.3.1、函数的参数
- 5.3.2、函数的返回值
- 5.3.3、匿名函数
- 5.3.4、函数的方法
- 5.4、对象的方法
- 5.5、this(上下文对象)
- 5.6、arguments
- 5.7、工厂动态创对象
- 5.8、构造函数
- 5.8.1、构造函数进阶
- 5.9、原型对象
- 5.10、toString()方法
- 拓展1:枚举对象中的属性
- 拓展2:垃圾回收(GC)
- 拓展3:class关键字
- 6、作用域
- 7、内建对象
- 7.1、数组
- 7.1.1、**length**
- 7.1.2、**数组字面量**
- 7.1.3、**数组中的元素可以是任意数据类型**
- 7.1.4、数组中常用方法
- 7.1.5、数组的遍历
- 7.2、Date对象
- 7.3、Math工具类
- 7.5、包装类
- 7.6、String对象常用方法
- 8、正则表达式
- 8.1、正则表达式字面量方式
- 8.2、字符串&正则表达式
- 8.3、正则表达式语法1
- 8.3、正则表达式语法2
- 9.DOM简介
- 9.1、DOM查询
- 9.1.1基本知识
- 节点
- 节点的属性
- 获取元素节点
- 元素节点的子节点
- 获取父节点和兄弟节点
- 9.1.2、查询剩余属性、方法
- 9.2、DOM删除
- 9.3、操作样式
- 9.3.1、操作内联样式
- 9.3.2、获取元素当前显示样式
- 9.3.3、其他样式操作的属性
- 9.4、事件
- 9.4.1、事件
- 9.4.2、事件对象
- 9.4.3、事件的冒泡
- 9.4.4、事件的委派
- 9.4.5、事件的绑定
- 9.4.6、bind()函数
- 9.4.7、事件的传播
- 9.4.8、拖曳
- 9.4.9、鼠标滚轮事件
- 9.4.10、键盘事件
- 10、BOM简介
- 10.1、Navigator
- 10.2、History
- 10.3、Location
- 10.4、定时器简介
- 10.4.1 定时器练习
- 10.4.2 div随键盘移动·改进
- 10.5、延迟调用
- 10.6、应用
- 10.6.1、定时器的应用
- 10.6.2、轮播图功能实现
- 10.7、类的操作
- 11、JSON
- 完结
javaScript概述
JavaScript 是一种基于对象和事件驱动并具有安全性能的脚本语言 。
JavaScript 官方名称是 “ECMAScript” (ECMA是欧洲电脑商制造协会)。
JavaScript 特点:
- 一种弱脚本语言
- 基于对象、动态性的
- 简单易用性、安全
- 跨平台性、改善用户体验
- 它是一种解释性程序语言。编译一行执行一行,而不像java一样,时完成了整个编译,然后再执行。
由来
网景公司想在原来的静态页面的基础上添加一些动态的效果,让用户体验更好,所以让布兰登·艾奇着手开发此功能。这位牛人仅用10天时间,便写出了javaScript。
这里不多赘述,感兴趣的朋友可以搜索一下哟!
1、javaScript基本知识
javaScript的Helloword
- alert:控制浏览器弹出一个警告框
- document.write(“ ”):向body中输出一个内容
- console.log(“ ”):向控制台输出一个内容
代码演示
<script>alert("helloWord");console.log("helloWord");document.write("helloWord");
</script>
1.2、JS编写位置
方式 一:在标签中写(不推荐 )
<a href="javascript:alert('太帅了!')">点我</a>
<button onclick="alert('真帅!')">点一下</button>
方式二:script标签中
<script type="text/javascript">alert("真帅!");</script>
方式三:外联js样式【写到外部的js文件,然后用script的src引入】推荐!!!
<script type="text/javascript" src="外部的js文件.js"></script>
注意:
script标签一旦用于 引用外部文件了,就不能在编写代码了,即使编写了浏览器也会忽略。如果你还需要,则可以在创建一个新的script标签用于编写内部代码
<script src="one.js">alert("do")</script>
如上,即使alert了,但不会有效果!
1.3、JS基本语法
- JS严格区分大小写
- 以
;
号结尾 - 会忽略多个空格和换行,所以我们可以利用空格和换行对代码进行格式化
1.4、变量与字面量
字面量:不可改变
1,2,3……n
变量
用var来 声明一个变量
注意:可以把字面量赋值给变量
var age =23;//变量
80 //字面量
局部变量
前提:idea需要设置ES6语法
建议都用let取定义局部变量(之前定义局部变量都是直接i=1),现在要let i =1
1.5、标识符
- 标识符:在JS中所有的可以由我们自主命名的都可以称为标识符
-例如:变量名、函数名、属性名都属于标识符
标识符命名规则: |
---|
1.标识符中可以含字母、数字、_、$ |
2.标识符不能以数字开头 |
3.标识符不能是ES中的关键字或保留字 |
4.标识符一般用驼峰命名 |
5.JS底层保存标识符实际上采用Unicode编码,所以 理论上讲,所有的 utf-8中含的内容都可以作为标识符 |
1.6、数据类型
数据类型:字面量的类型
JS的6中数据类型
数据类型 | 释意 |
---|---|
String | 字符串 |
Number | 数值 |
Boolean | 布尔值 |
Null | 空值 |
Undefined | 未定义 |
Object | 对象 |
拓展:其中String Number Boolean Null Undefined
为基本数据类型,Object
属于引用数据类型
1.6.1、Number详解
在JS中所有的数值都是Number
类型,包括整数和浮点数(小数)
- JS中可以表示数字的最大值和最小值
Number.MAX_VALUE;
1.7976931348623157e+308Number.MIN_VALUE //大于0的最小值
5e-324
-
如果使用Number表示的数字 超过了最大值,则会返回一个
Infinity
表示正无穷
-Infinity
表示负无穷 使用typeof检查Infinity也会返回number
-
NaN 是一个特殊的数字,表示Not A Number
使用typeof检查一个NaN也会返回number
拓展:typeof检查变量的类型
let i =1;//局部变量声明用letalert(typeof i);//返回number
注意:
如果使用JS进行浮点运算,可能得到一个不精确的结果
所以,千万不要使用JS进行对精确要求比较高的运算
console.log((1/3)==(1-2/3));//这里会返回false,尽管数值都为1/3,尽量避免使用小数计算
1.6.2、布尔值
布尔值只有两个,主要用来做逻辑判断
true
表示真
false
表示假
使用typeof检查一个布尔值,返回boolean
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>布尔值</title><script>var bool =true;console.log(bool);console.log(typeof bool)</script>
</head>
<body></body>
</html>
1.6.3、Null 和undefined
-
Null(空值)类型的值只有一个,就是null
null这个值专门用来表示一个为空的对象
使用typeof检查一个null值时,返回object
-
undefined(未定义)类型的值只有一个,就undefind
当声明一个变量,但是并不给变量赋值时,它的值就是undefined
使用typeof检查一个undefined时也是undefined
1.7、强制类型转换
强制类型转换
– 指将一个数据类型强制转换为其他的数据类型
– 类型转换主要指,将其他的类型,转换为String、Number、Boolean
1.7.1、将其他的数据类型转换为String
方式一:
-
调用被转换数据类型的toString()方法
-
该方法不会影响原变量,它会将转换的结果返回
-
但是注意:
null 和 undefined 这两个值没有toString()方法,如果调 用他们的方法会报错
方式二:
- 调用String()函数,并将被转换的数据作为参数传递给函数
- 使用String函数做强制转换时;
- 对于Number和Boolean实际上就是调用的toString()方法
- 但是对于Null和undefined,就不会调用toString()方法
- 它会将null 直接转换为“null”
- 将undefined直接转换为“undefined”
代码实现
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>强制类型转换</title><script>// 方式一:var a =123;a =a.toString();console.log(typeof a);console.log(a);var b =true;b =b.toString();console.log(typeof b);console.log(b);//方式二:a2 =String(a);console.log( typeof a2);console.log(a2);var d =null;d =String(d);console.log(typeof d);console.log(d);</script>
</head>
<body></body>
</html>
1.7.2、将其他数据类型转换为Number
转换方式一:使用Number()函数
- 字符串-------》数字
- 如果是纯数字的字符串,则直接将其转换为数字
- 如果字符串中有非数字的内容,则转换为NaN
- 如果字符串是一个空串或者是一个全是空格的字符串,则转换为0;
- 其他--------》数字
类型 | 数字 |
---|---|
true | 1 |
false | 0 |
null | 0 |
undefined | 数字NaN |
转换方式二:
这种方式专门用来处理字符串,如果对非字符串使用parseInt()或parseFloat(),它会先将其转变为String类型,再操作
- parseInt(参数) 把一个字符串转换为一个整型数
- parseFloat(参数) 把一个字符串转换为一个浮点数
1.7.3、将其他进制转换成布尔类型
使用Boolean()函数
-
数字 ======》 布尔
- 除了0和NaN,其余都是**true**
-
字符串 ====》 布尔
- 除了空串,其余的都是true
-
其他类型
- null和undefined都会转换false
- 对象也会转换为true
1.7.4、其他进制的数字
在JS中,
- 如果需要表示16进制的数字,则需要以0x开头
var a =0x10;
console.log(a); //16
- 如果需要表示8进制的数字,则需要以0开头
var a =010;
console.log(a); // 8
- 如果需要表示2进制 的数字,则需要以0b开头,但不是所有的浏览器都支持
var a =0b10;
console.log(a); //2
拓展:
如你想解析字符串为数字,"070"
,有些浏览器会当成8进制解析,有些则会当成10进制解析。为了避免你可能这里式10进制解析,那里又是8进制解析,我们在使用parseInt()时,一般指定进制。
格式如下:parseInt(参数,指定进制)
var a =070;
a =paseInt(a,10);//指定为10进制
a =paseInt(a,2);//指定2进制
代码实现
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>其他进制的数字</title><script>//16进制var a ="0x70";console.log(a);//8进制var b ="070";console.log(b);//2进制var c ="0B10";//并不是所有浏览器就支持console.log(c);var str ="=====================";console.log(str);var d ="070";d =parseInt(d,10);console.log(d);d =parseInt(d,8);console.log(d)d =parseInt(d,2);console.log(d);</script>
</head>
<body></body>
</html>
拓展:严格检查模式
IDEA需要设置支持ES6语法,'use strict';
严格检查模式,预防javaScript的随意性导致的一些问题.
前提:idea需要设置支持ES6语法。
2、算数运算符
当对非Number类型的值进行运算时,会将这些值转换Number然后在运算
任何值和NaN做运算都得NaN
+
+可以对两个值进行加法运算,并将结果返回
如果对两个字符串进行加法运算,则会进行拼串处理:会将两个字符串拼接成一个字符串,并返回
任何的值和字符串做加法,都会先转换为字符串,然后再和字符串做拼串操作
-
-可以对两个值进行减法运算,并将结果返回
*
可以对两个值进行乘法运算
/
可以对两个值进行除法运算
注意:
- 任何值做- * / 运算时都会自动转换为Number
我们可以利用这个特性做隐式的类型转换
可以通过为一个值 - 0 *1 /1
来将其转换为Number
原理和Number()函数一样,使用起来更简单
- 同理:
也可以利用任何的值和字符串做加法都会先转换为字符串,然后再和字符串做拼串操作
的特点,来进行隐式类型转换。
可以通过数字+""
来将其转换为字符串。原理也和String()函数
一样,使用起来更简单。
- 其他类型
true | 1 |
---|---|
false | 0 |
null | 0 |
undefined | NaN |
2.1、一元运算符
一元运算符:只需要一个操作数
+
正号
不会对数字产生任何影响
-
负号
负号可以对数字进行符号的取反
注意:
对于非Number类型的值
它会将类型先转换为Number,然后在进行运算
可以对一个其他的数据类型使用+,来将其转换为Number
它的原理和Number()函数一样、
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>一元运算符</title><script>var a =true;a =-a;console.log(a)//-1var b ="123";b =+b;console.log(b);//123var c =1 + +"2" +3+ +"4";console.log(c)//10</script>
</head>
<body></body>
</html>
2.2、自增与自减运算符
- 自增
- 自增可以使变量在原值的基础上自增1
- 自增使用
++
- 自增可以使用
a++
,与++a
- 无论是++a还是a++动员会立即使原变量自增1
- 不同的式
++a
和a++
的值式不同的++a
的值是变量的新值(自增后的值)a++
的值是变量的原值(自增前的值)
- 不同的式
- 自减
- 自减可以使变量在原值的基础上自减1
- 自减使用
--
- 自减可以使用
--a
与a--
- 无论是
--a
还是a-
-都会立即使原变量自减1- 不同的是–a和a–的值
--a
的值是变量的新值(自减后的值)a--
的值是变量的原值(自减前的值)
- 不同的是–a和a–的值
- 自减使用
2.3、逻辑运算符
JS中为我们提供了三种逻辑运算符
2.3.1、布尔判断
-
!
非-
! 可以用来对一个值进行非运算
-
所谓非运算就是值对一个布尔值进行取反操作
- true便false false 便true
-
如果对一个值进行两次取反,它将不会发生变化
-
如果对非布尔类型的元素进行取非,它将会转换为布尔值在取反
-
所以我们可以利用该特点,来将一个其他的数据类型转变为布尔类型
-
可以为一个任意数据类型取反两次,来将其转换为布尔值
-
原理和Boolean()函数一样
-
-
-
&&
与-
&&可以对符号两侧的值进行与运算并返回结果
-
运算规则
- 两个值中只要有一个值为false就返回false
- 只有两个值都为true时,才会返回true
- 两个值中只要有一个值为false就返回false
-
JS中的”与“属于短路与
- 如果第一个值为false,则不会去看第二个值
-
-
||
或-
|| 可以对符号两侧的值进行或运算并返回结果
-
运算规则:
- 两个值只要有一个true,就返回true
- 如果两个值都为false,才会返回false
- 两个值只要有一个true,就返回true
-
JS中的”或“属于短路的或
- 如果第一个值为true,则不会检查第二个值
-
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>逻辑运算符</title><script>true || alert("我是天下第一");//因为第一个是true了,无论第二个是不是true,// 结果都会放回true,所以它不会去管第二个值,false && alert("我是天下第一");//&& 这个是短路与, 一旦第一个值为false,就不回去管第二个值了true && alert("我是天下第一");//因为这个是第一个值且为true,它会去看第二个值,以来判断整段表达式</script>
</head>
<body></body>
</html>
2.3.2、非布尔判断
&& 与 || 非布尔值的情况
对于非布尔值进行与或运算时,会对其转换为布尔值,然后在运算,并且返回原值
-
与运算
-
如果第一个值时true,则必然返回第二个值
-
如果第一个值时false,则之间返回第一个值
-
-
或运算
- 如果第一个值是true,直接返回第一个值
- 如果第一个值是false,则返回第二个值
// false false//第一个为false了,不用看第二个直接返回第一个var result = NaN && 0;console.log(result)var c =0 && NaN;console.log(c)// TRUE FALSE// 第一个是正确的,那么整段逻辑表达式取决于第二个值,所以它会直接返回第二个值var a =true && false;console.log(a);
2.3.3、判断运算符
非数值的情况
- 对于非数值进行比较时,会将其转换为数字然后再比较
- 如果符号两侧都是字符串是,不会将其转换为数字进行比较,而是会分别比较字符串中字符的Unicode编码,一个字符一个符的比
2.3.4、转义字符
在HTML中转义,用&#编码;
编码为10进制的数制
var a ="\u2620";//\为转义,u标明输出为unicode字符集console.log(a);
在JS中用\u
,\
代表转义,u
指明输出的字符集
<h1 style="font-size: 1000px " align="center">☠</h1>
2.3.5、相等运算符
想等运算符用来比较两个值是否相等,如果相等会返回true,否则返回false
-
使用==来做相等运算
- 大部分使用==来比较两个值是,如果值的类型不同,则会继续自动类型转换,将其转换为相同的类型,然后比较
-
不相等 !=
- 不相等用来判断两个值是否不相等,如果不相等返回true,否则返回false
- 使用!=来做不相等运算
- 不相等也会对变量进行自动类型转换,如果转换后相等,则返回false,不相等则返回true
-
全等
- 用来判断 两个值是否相等,它和相等类似,不同的是它不会做自动类型转换,如果两个值的类型不同直接返回false
-
不全等
- 用来判断两个值是否不全等 ,和不等类型,不同的是它也不会自动转换类型。如果两个值的类型不同,直接 返回true
拓展:
- NaN不和任何值相等,包括他本身
undefined
衍生自null
,所以这两个值做相等判断时,会返回true,所以我们在做变量值是否为NaN时,**不能用== 而是用isNaN()**函数- 尽量不要用== 来做判断,类型不一样,值一样也会返回true
2…3.6、三目运算符(三元运算符)
语法:
条件表达式?语句1:语句2;
-
执行的流程:
-
条件运算符在执行时,首先对条件表达式进行求值
- 如果该值为true,则执行语句1,并返回执行结果
- 如果该值为false,则执行语句2,并返回执行结果
-
如果条件的表达式的求值结果是一个非布尔值,会将其 转换为布尔值然后再运算
-
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>三元运算符</title><script>var a = 10;var b = 20;var c = 50;var max = a > b ? alert("a大") : alert("b大");max = max > c ? max : c;console.log(max);//不建议,这么写var max = a > b ? (a > c ? a : c) : (b > c ? b : c);console.log(max);</script>
</head>
<body></body>
</html>
2.3.7、运算符优先级
就像数学中一样,在JS中运算符也有优先级
比如:先乘除,后加减
在JS中有一个运算符优先级的表,
在表中越靠上优先级越高,优先级越高越优先计算,如果优先级也有,则从左往右计算。
查看优先级:运算符优先级 - JavaScript | MDN (mozilla.org)
优先级 | 运算符类型 | 结合性 | 运算符 | 高低 |
---|---|---|---|---|
21 | 圆括号 | n/a(不相关) | ( … ) | 高 ↑ |
20 | 成员访问 | 从左到右 | … . … | |
需计算的成员访问 | 从左到右 | … [ … ] | ||
new(带参数列表) | n/a | new … ( … ) | ||
函数调用 | 从左到右 | … ( … ) | ||
可选链(Optional chaining) | 从左到右 | ?. | ||
19 | new(无参数列表) | 从右到左 | new … | |
18 | 后置递增 | n/a | … ++ | |
后置递减 | … – | |||
17 | 逻辑非 (!) | 从右到左 | ! … | |
按位非 (~) | ~ … | |||
一元加法 (+) | + … | |||
一元减法 (-) | - … | |||
前置递增 | ++ … | |||
前置递减 | – … | |||
typeof | typeof … | |||
void | void … | |||
delete | delete … | |||
await | await … | |||
16 | 幂 (**) | 从右到左 | … ** … | |
15 | 乘法 (*) | 从左到右 | … * … | |
除法 (/) | … / … | |||
取余 (%) | … % … | |||
14 | 加法 (+) | 从左到右 | … + … | |
减法 (-) | … - … | |||
13 | 按位左移 (<<) | 从左到右 | … << … | |
按位右移 (>>) | … >> … | |||
无符号右移 (>>>) | … >>> … | |||
12 | 小于 (<) | 从左到右 | … < … | |
小于等于 (<=) | … <= … | |||
大于 (>) | … > … | |||
大于等于 (>=) | … >= … | |||
in | … in … | |||
instanceof | … instanceof … | |||
11 | 相等 (==) | 从左到右 | … == … | |
不相等 (!=) | … != … | |||
全等 (===) | … === … | |||
不全等 (!==) | … !== … | |||
10 | 按位与 (&) | 从左到右 | … & … | |
9 | 按位异或 (^) | 从左到右 | … ^ … | |
8 | 按位或 (|) | 从左到右 | … | … | |
7 | 逻辑与 (&&) | 从左到右 | … && … | |
6 | 逻辑或 (||) | 从左到右 | … || … | |
5 | 空值合并 (??) | 从左到右 | … ?? … | |
4 | 条件(三元)运算符 | 从右到左 | … ? … : … | |
3 | 赋值 | 从右到左 | … = … | |
… += … | ||||
… -= … | ||||
… **= … | ||||
… *= … | ||||
… /= … | ||||
… %= … | ||||
… <<= … | ||||
… >>= … | ||||
… >>>= … | ||||
… &= … | ||||
… ^= … | ||||
… |= … | ||||
… &&= … | ||||
… ||= … | ||||
… ??= … | ||||
2 | yield | 从右到左 | yield … | |
yield* | yield* … | |||
1 | 逗号 / 序列 | 从左到右 | … , … | 低 |
图示
3、代码块
我们的程序由一条条语句构成的,语句是按照自上而下的顺序一条条执行。
在JS中可以使用{}来进行分组,它们要么都执行,要么都不执行。一个{}中的语句,我们称为一个代码块,在代码块后,不需要写;
了。
JS的代码块,只具有分组作用,没有其他用途(这里与java不一样)
4、流程控制
4.1、if语句
与java中的if语法一样
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>流程控制</title><script>alert("请输入三个不相等的数字")var imput1 =prompt("请输入第一个数值");//prompt 返回值 是String型var imput2 =prompt("请输入第二个数值");var imput3 =prompt("请输入第三个数值");if(isNaN(imput1) || isNaN(imput1) ||isNaN(imput1)){alert("数字为NaN")}else {if(imput1>imput2){if(imput1>imput3){alert(imput1);}else {alert(imput3);}}else{if(imput2>imput3){alert(imput2);}else {alert(imput3);}}}</script>
</head>
<body>
</body>
</html>
4.2、switch语句
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>switchEx</title><script>//方式一:与java一样var score = 55;switch (parseInt(score / 10)) {case 10 :case 9 :case 8 :case 7 :case 6 :console.log("及格");break;default:console.log("不合格")break;}//方式二:JS中独有switch (true) {case score >= 60: {console.log("合格");break;}default: {console.log("不合格");break;}}</script>
</head>
<body></body>
</html>
4.3、while循环语句
- while
var num =1;while (num<=10){document.write(num++ +"<br/>");//如果用javascipt的document.write("\n")输出到html内,只是一个换行符,并不能起到真正换行的作用。}
- do while循环
var num =1;do{document.write(num++ +"<br/>");}while (num<=0);
4.4、for循环
for (var i = 100; i <1000 ; i++) {var bai =parseInt(i/100);var shi =parseInt((i-bai*100)/10);var ge =i%10if(bai*bai*bai+shi*shi*shi+ge*ge*ge == i){console.log(i);}}
5、自定义对象
对象属于一种复合的数据类型,在对象中可以保存多个不同数据类型的属性
对象的分类:
-
内建对象
- 由ES标准中定义的对象,在任何的ES的实现中都可以使用
- 比如:Math String Number Boolean Function Object……
-
宿主对象
- 由JS的运行环境提供的对象,目前来讲主要指浏览器提供的对象
- 比如:BOM DOM
-
自定义对象
- 由开发人员自己创建的对象
创建对象
var obj =new Object();
给对象属性赋值
obj.name ="李天启";
注意:
这个不像java中一样,不需要再上面定义,你直接.属性名
这样就可以定义。但这时没赋值的!
删除属性
delete obj.age;//删除对象属性
5.1、对象的属性
对象的属性名不强制要求遵守标识符的规范,意味着什么乱七八糟的名字都可以使用,但是我们使用还是要按照标识符规范去做。
如果要使用特殊的属性名,不能采用.属性名
的方式来操作,而是需要采用另一种方式:
语法:对象["属性名"]=属性值
obj[123] = 789;//1
obj["123"] = 456;//2
console.log(typeof obj["123"]);//其实1和2要说明的是同一个属性,它会自动类型转换为数字
注意:
使用[]
这种形式去操作属性,更加灵活,再[]
中可以直接传递一个变量,这样变量值是多少就会读取那个属性
var n ="I love You";
obj["I love You"] ="谢谢";
console.log(obj[n]);//输出谢谢
拓展:
in
运算符
- 通过此运算符可以检查一个对象中是否含有指定的属性
- 有返回true,没有返回false
语法:"属性名" in 对象
console.log( "name" in obj);console.log( ["I love You"] in obj);
切记:
你在用in的时候要用""
括起来,如果它是字符串类的就不用了。
拓展章节:基本数据类型与引用数据类型
在JS的变量都是保存到栈内存中,基本数据类型的值直接在栈内存中存储,值与值之间是独立存在,修改一个变量不会影响其他变量
对象是保存到堆内存中的,没创建一个新的对象,就会在堆内存中开辟出一个新的空间,而变量保存的是对象的内存地址(对象的引用),如果两个变量保存的是同一个对象引用时,当其中一个通过一个变量修改属性时,另一个也会受到影响。
对象是保存到堆内存中的,每创建一个新的对象,就会在堆内存中开辟出一个新的空间,而变量保存的是对象的内存地址(对象的引用),如果两个变量保存的是同一个对象引用时,当其中一个通过一个变量修改属性时,另一个也会受到影响。
图示
5.2、对象字面量
使用对象字面量,可以在创建对象时,直接指定对象的属性
var obj ={};//对象字面量,这样写和new Object()这样,本质是一样的。
var obj1 ={name:"李白",age:21,sex:"男",ability:{xingNeng:"超神"}
};
- 语法:
{属性名:属性值,属性名:属性值,属性名:属性值……}
对象字面量的属性名可以加引号也可以不加,<font color='red'>建议不加</font>;如果要使用一些特殊的名字,则必须加引号。
- 属性名与属性值
属性名和属性值是一组一组的名值堆结构
名和值之间使用:
连接,多个名值对之间用,
隔开
如果一个属性之后没有其他的属性了,就不要写,
5.3、函数
-
函数
- 函数也是一个对象
- 函数中可以封装一些功能(代码),在需要时可以执行这些功能(代码)
- 该函数中可以保存一些代码在需要的时候调用
- 使用typeof检查一个函数对象时,会返回function
-
创建一个函数对象
-
可以将要封装的代码以字符串的形式传递给构造函数
-
封装到函数中的代码不会立即执行
-
函数中的代码会在函数调用的时候执行
-
调用函数语法:
函数对象();
-
当调用函数时,函数封装的代码会按照顺序执行
-
var fun =new Function ("console.log('这是我第一个函数');");//注意:log括号后要加上;,因为它是一个语句,只不过被封装了而已fun();
注意:其实我们在开发的时候极少,甚至不使用这种利用构造函数创建一个函数
- 使用 函数声明 来创建一个函数(推荐)
语法:
function 函数名([形参1,形参2,……形参N]){
语句……
}
//方式一:var fun = new Function("console.log('这是我第一个函数');");//注意:log括号后要加上;,因为它是一个语句,只不过被封装了而已,一般不用fun();//方式二:function fun2() {// 推荐console.log("我要加油!")}fun2();//方式三:var fun3 = function(){console.log("我是匿名函数");};//这里是个赋值语句,所以要加分号fun3();
5.3.1、函数的参数
- 可以在函数的()中指定一个或多个形参(形式参数)
- 多个形参之间使用
,
隔开,声明形参就相当于在函数声明了对应的变量,但是并不赋值 - 在调用函数时,可以在()中指定实参(实际参数),实参将会赋值给函数中对应的形参
注意:
- 调用函数时,解析器不会检查实参的类型。【所以要注意,是否有可能会接收到非法的参数,如果有可能则需要对实参进行类型的检查】
- 调用函数时,解析器也不会检查实参的数量,多余的实参不会被赋值
- 如果实参的数量少于形参的数量,则没有对应实参的参数将是undefined
- 实参可以是任意类型。
代码演示
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>函数的参数</title><script>function sum (a,b){console.log("a="+a);console.log("b="+b);console.log(a+b);}sum(123,456);sum(123);//因为b没有赋值,所以它是undefined,两者相加变成了NaNsum(123,"abc");sum(123,789,"abc",true);sum(true,false);</script>
</head>
<body>
</body>
</html>
5.3.2、函数的返回值
- 可以使用
return
来设置函数的返回值
语法:
return 值
注意:
-
return后的值将会作为函数的执行结果返回,可以定义一个变量来接收该结果
-
函数返回声明result的值就是什么
-
return后的语句不会执行
-
如果函数中不写return,则会返回undefined
-
如果函数后不带值,也会返回undefined
-
return后的值可以是任意类型
代码实现
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>函数的返回值</title><script>function sum(a,b,c){var d =a+b+c;}var result =sum(1,2,3);console.log(result);//因为sum函数中没有写return,则result的结果将是undefinedfunction sum1(a,b,c){var d =a+b+c;return;}var result1 =sum(1,2,3);console.log(result1);//因为return后不加任何值,将会返回undefinedfunction sum2(a,b,c){var d =a+b+c;return d;}var result3 =sum2(1,2,3);console.log(result3);//实参可以任何类型,可以是一个对象,也可以是一个函数function sayHello(obj) {console.log("我叫" + obj.name + ",来自" + obj.address);}sayHello(obj);</script>
</head>
<body></body>
</html>
注意:
mianji()
// -调用函数
// -相当于使用函数的返回值
mianji
// -函数对象
// -相当于直接使用函数对象
==================================================function fun1(){return fun4();}fun1();function fun4(){console.log("我是fun4");}function fun(){return fun4;}fun1()();//这里相当于直接调fun4var a =fun1();a();//这里于上面写法一样
5.3.3、匿名函数
- 立即执行函数
- 函数定义完,立即被调用,这种函数叫做立即调用函数
- 立即执行函数往往只会调用一次
(function (){console.log("我是立即执行函数");})();(function (a,b){console.log(a+b);})(123,456);
5.3.4、函数的方法
call()和 apply()
这两个方法都是函数对象的方法,需要通过函数对象来调用
当对函数调用call()和apply()都会调用函数执行对象
在调用call()和apply()可以将一个对象指定为第一个参数,此时这个对象将会成为函数执行时的this
call()方法可以将实参在对象之后依次传递
apply()方法需要将实参封装到一个数组中统一传递
-
实参的个数由函数的形参确定
-
this的情况:
- 以函数形式调用时,this永远都是window
- 以方法的形式调用时,this是调用方法的对象
- 以构造函数的形式调用时,this新创建的那个对象
- 使用call和apply调用,this时指定的那个对象
5.4、对象的方法
- 函数也可以称为对象的属性
- 如果一个函数作为一个对象的属性保存那么我们称这个函数是这个对象的方法
- 届时,调用函数就说:调用对象的方法
- 但它们只是名称上的区别,没有其他的区别
var obj ={name:"李天启",sayName:function (){console.log(obj.name);}}obj.sayName();
==============================var obj1 =new Object();obj1.name="神";obj1.sayName=function (){console.log(obj1.name);}obj1.sayName();
5.5、this(上下文对象)
解析器在调用函数时,每次都会向函数内部传递进一个隐含的参数,这个隐含的参数就时this,this指向的是一个对象,这个对象我们称为函数执行的上下文对象。
- 根据函数的调用方式的不同,this会指向不同的对象
- 以函数的形式调用时,this永远都是window
- 以非法的形式调用时,this就是调用方法的那个对象
var name ="全局";
function fun(){console.log(this.name);
}
var obj1 ={name:"😁",sayName:fun
}
var obj2 ={name:"hah",sayName: fun
}fun();//全局 相当于window.fun();
obj1.sayName();
obj2.sayName();
5.6、arguments
-
在调用函数时,浏览器每次都会传递进两个隐含的参数
- 函数的上下文对象
- 封装实参的对象arguments
-
arguments
是一个类数组对象(不是数组),它可以通过索引来操作数据,也可以获取长度-
在调用函数时,我们所传递的实参都会在argument中保存
-
arguments.length可以用来获取实参的长度
-
我们即使不定义形参,也可以通过argunments来使用实参,只不过比较麻烦
- arguments[0]表示第一个参数
- arguments[1]表示第二个参数
-
它里边有一个属性叫做
callee
,这个属性对应一个函数对象,就是当前正在指向的函数的对象
-
5.7、工厂动态创对象
function produceObject(name,age,gener){var obj =new Object();obj.name=name;obj.age =age;obj.gener=gener;obj.sayName=function(){console.log(this.name);}return obj;//将新对象返回}var obj =produceObject("孙悟空",21,"男");
var obj1 =produceObject("小狐狸",22,"女");
var obj2=produceObject("小红枣",20,"男");
obj.sayName();
obj1.sayName();
obj2.sayName();
5.8、构造函数
构造函数就是一个普通的函数,创建方式和普通函数没有区别,不同的时构造函数习惯上首字母大写
- 构造函数和普通函数的区别就是调用方式的不同
- 普通函数是直接调用,而构造函数需要使用new关键字来调用
构造函数的执行流程:
- 立刻创建一个新的对象
- 将新建的对象设置为函数中this,在构造函数中可以使用this来引用新建对象
- 逐行执行函数中的代码
- 将新建的对象作为返回值返回
- 使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类
- 我们将通过一个构造函数创建的对象,称为该类的实例
this的情况:
- 当以函数的形式调用时,this时指window
- 当以方法的形式调用时,谁调用方法this就是谁
- 当以构造函数的形式调用时,this就是新创建的那个对象
代码演示
function Person(name,age,sex){this.name =name;this.age =age;this.sex =sex;this.sayName =function (){console.log(this.name);};
}
var per =new Person("李天启",21,"男");
console.log(per);
console.log(per instanceof Person);
5.8.1、构造函数进阶
创建一个Person函数
在Person构造函数中,为每一个对象都添加了sayName方法,目前我们的方法是构造函数内部创建的,也就是构造函数每执行一次就会创建一个新方法,执行10000次就会创建10000个新方法,而10000个方法都是一模一样的,这是完全没有必要,完全可以使所有的对象共享一个方法
解决方法:把这个方法放在全局作用域中即可
代码演示
function Person(name,age,sex){this.name =name;this.age =age;this.sex =sex;this.sayName =function (){console.log(this.name);};
}
var per =new Person("李白",21,"男");
var per1 =new Person("杜甫",20,"女");
per.sayName();
per1.sayName();
console.log(per.sayName == per1.sayName);//false//进阶:
function Person1(name,age,sex){this.name =name;this.age =age;this.sex =sex;this.sayName =fun;
}
function fun(){console.log(this.name);
}
var per2 =new Person1("李天男",24,"男");
per2.sayName();
var per3 =new Person1("李天女",21,"女");
per3.sayName();console.log(per2.sayName()==per3.sayName());//true
缺点:
- 将函数定义在全局作用域,污染了全局作用域的命名空间
- 而且定义在全局作用域中也很不安全。【比如,有另外一个程序员,他也定义了和你同名的方法,这时运行时报错,几千行代码,他要排很长时间】
5.9、原型对象
原型prototype
我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype
这个属性对应着一个对象,这个对象就是我们所谓的原型对象
- 如果函数作为普通函数调用prototype没有任何作用
- 当函数一构造函数的形式调用时,他所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象,我们可以通过
__proto__
来访问该属性
原型对象相当于一个公共区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一到原型对象中
当我们访问对象的一个属性或方法时,它会现在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如找到则直接使用
以后我们创建构造函数时,可以将这些对象的共有属性和方法,同意添加到构造函数的原型对象中,这一不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具备这些属性和方法了
- 原型对象也是对象,所有它也有原型,当我们使用一个对象的属性或方法时,会在自身中寻找;自身中如果有,则直接使用,如果没有则去原型对象中寻找,如果原型对象中有,则使用,如果没有则去原型对象的原型对象中去寻找,直到找到Object对象的原型,Object对象的原型对象没有原型对象【null】,如果在Object原型对象中依然没有找到,则返回undefined
5.10、toString()方法
若我们在网页中直接输出对象,那打印的是[Object Object]。所以我们可以在该类【原型对象】中,添加一份toString函数。
function Person(name,age, sex){this.name =name;this.age =age;this.sex =sex;}Person.prototype.toString = function (){return "Person[name:"+this.name+",age:"+this.age+",sex:"+this.sex+"]";};var per =new Person("李天启",21,"男");var per1 =new Person("李白",20,"男");alert(per);alert(per1);
拓展1:枚举对象中的属性
使用for in语句
语法:
for(var 变量 in 对象){循环体//for...in对象中有几个属性,循环体就执行几次}
代码演示
var obj ={name:"李自在",sex:"男",age:21,sayName:function (){console.log(obj.name);}
}
for (var n in obj) {console.log(n);//输出属性名console.log(obj[n]);//输出属性值
}
//切记不可obj.n === obj中没有n这个属性,会循环输出undefined
//obj["n"]也同上,但obj[n],这里的n就是变量。
拓展2:垃圾回收(GC)
就想人生活的时间常量会产生垃圾一样,程序运行过程中也会产生垃圾,这些垃圾积攒过多以后,会导致程序运行的速度过慢,使用我们需要一个垃圾回收的机制,来处理程序运行过程中产生的垃圾。
当一个对象没有仍和的变量或属性对它进行引用,此时我们将永远无法操作该对象,此时这种对象就想一个垃圾,这种对象过多占用大量的内存空间,导致程序运行变慢,使用这种垃圾必须进行清理。
在JS拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,我们不需要也不能进行垃圾回收操作,我们需要做得只是要将不再使用的对象设置为 Null即可。
拓展3:class关键字
- 继承
class student {constructor(name) {this.name = name;}age = 10;hell() {alert("hello");}
}
class xiaoming extends student{constructor(name,grade) {super(name);this.grade =grade;}myGrade(){alert("我是个大学生!");}
}
var a=new xiaoming("xiaohong",1);
a.hell();
a.myGrade();
本质:其实还是利用了原型对象
6、作用域
作用域
-
作用域指一个变量作用的范围
-
在JS中一共有两种作用域
全局作用域
-
直接写在script标签中的JS代码,都在全局作用域
-
全局作用域在页面打开时创建,在页面关闭时销毁
-
在全局作用域中有一个全局对象window
- 它代表的时一个浏览器的窗口,它由浏览器创建我们可以直接使用
-
在全局作用域中:
-
创建的变量都会作为window对象的属性保存
-
创建的函数都会走位window对象的方法保存
-
在全局作用域在的变量都是全局变量
- 在页面的任意部分都可以访问到
变量的声明提前
使用var
关键字声明的变量,会在所有的代码执行之前杯声明(但不会被赋值),但是如果声明变量时,不是用var关键字,则变量不会被声明提前(局部变量一般用let【ES6】)
函数的声明被提前
使用函数声明形式创建的函数function 函数(){}
,它会在所有代码执行之前就被创建,所有我们可以在函数声明前调用函数
使用函数表达式创建的函数,不会被声明提前,使用不能在声明前调用
函数作用域
调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁
每调用一次函数就会创建一个新的函数作用域,他们之间时相互独立
在函数作用域中可以访问到全局作用域的变量
当在函数作用域操作一个变量时,它会现在自身作用域中寻找,如果有就直接使用【就近原则】
如果没有就向上一级作用域中找,指导找到全局作用域,如果全局作用域中依然没有找到,就会报错ReferenceError
在函数中要访问全局变量可以使用window对象
注意:
- 在函数作用域也有声明提前的特性,使用
var
关键字声明的变量,会在函数中所有的代码执行之前被声明 - 函数声明也会在函数中所有代码执行之前执行
- 在 函数中,不使用
var
声明的标量都会称为全局变量 - 定义形参就相当于在函数作用域中声明了变量
7、内建对象
7.1、数组
JS的数组和java中的数组基本一样,不同的是,java读取不存在的索引会报错,而它不会报错,而是返回undefined
7.1.1、length
设置和获取数组的长度
数组.length
- 对于看来连续的数组,使用length可以获取数组的长度(元素的个数)
- 对于非连续数组,使用length会获取到数组的最大索引+1
尽量不要创建非连续的数组
修改length
- 如果修改的length大于原长度,则多出部分会空出来
- 如果修改的length小于原长度,则多出的元素会被删除
向索引后一个位置添加值
//连续数组var arr =new Array();arr[0] =10;arr[arr.length] =20;//向后添加一个元素console.log(arr[0]);console.log(arr[1]);console.log(arr[5]);//undefinedconsole.log(arr.length);//2//不连续数组var arr1 =new Array();arr1[0] =30;arr1[10] =5;console.log(arr1[5]);console.log(arr1.length);//11 最大索引加1
7.1.2、数组字面量
语法: var arr =[元素,元素,……];
//数组字面量创建【推荐使用】
var arr2 =[10,20,30];
//创建了长度为1,元素为10的数组
var arr2 =[10];
//创建了长度为10的数组
var arr3 =new Array(10);
//创建了长度为3,元素分别为10,20,30的元素
var arr4 =new Array(10,20,30);
7.1.3、数组中的元素可以是任意数据类型
可以是函数,对象,数字,字符串,null,undefined,数组等任意数据类型,哪怕混存也可以!
代码演示
//数组存储任意数据类型var obj =new Object();var arr5 =[true,undefined,null,"lalla",function (){},obj];console.log(arr5);
// 二维数组
var arr6 =[[1,2,3],[4,5,6],[7,8,9]];
console.log(arr6[0]);
7.1.4、数组中常用方法
push()
- 该方法可以向数组的末尾添加一个或多个元素,并返回数组的新长度
- 可以将要添加的元素作为方法的参数传递,这样这些元素将会自动添加到数组的末尾
- 该方法会将数组的新长度作为返回值返回
var arr =[10,20,30];arr.push(40,50,60);console.log(arr);//10,20,30,40,50,60console.log(arr.length);//6
pop()
- 该方法可以删除数组的最后一个元素,并将被删除的元素作为返回值返回
var arr =[10,20,30];arr.pop();console.log(arr);
unshift()
- 该方法向数组开头添加一个或多个元素,并返回新的数组长度
- 向前插入元素以后,其他的元素会依次调整
var arr =[10,20,30];
arr.unshift(0);
console.log(arr);//0,10,20,30
console.log(arr.length);//3
shift()
- 可以删除数组的第一个元素,并将删除的元素作为返回值返回
var arr =[10,20,30];arr.shift();console.log(arr);//20,30console.log(arr.length);//2
slice()
-
可以用来从数组中提取指定元素
-
该方法不会改变元素数组,而是将截取到的元素封装刀一个新数组中,并将该数组返回
-
参数:
- 截取开始位置的索引,包含开始索引
- 截取结束的位置索引,不包含结束索引
- 第二个参数可以省略不写,此时会截取从从开始索引往后的所有元素
3.索引可以传一个负数,如果传的是负数,那便从后往前计算
-1 倒数第一个
-2 倒数第二个
代码演示
var arr =[10,20,30,40,50];
var result =arr.slice(1);//如果只传一个索引值,那便会从1截取到后面所有(长度索引位置)
console.log(result);
var result1 =arr.slice(0,-2);//截取0位置到数组倒数第二个console.log(result1);var result2 =arr.slice(1,3);console.log(result2);
splice()
-
可以用于删除数组中指定元素
-
使用splice()会影响到原数组,会将指定元素从原数组中删除,并将被删除的元素作为返回值返回
-
参数:
- 第一个:表示开始位置的索引
- 第二个:表示删除元素的数量
- 第三个及以后:可以传递一些新元素,这些元素将会自动插入到原开始位置索引的位置
var arr =[10,20,30,40,50];arr.splice(0,2,503,911);console.log(arr);
去重练习
var arr =[1,2,3,2,1,3,4,2,5];
for (var i = 0; i < arr.length; i++) {for (var j = i+1; j < arr.length; j++) {if(arr[i]==arr[j]){arr.splice(j,1);j--; }}
}
console.log(arr);
concat()
- 可以连接两个或多个数组,并将新的数组返回
- 该方法不会对原数组产生影响
- 也不仅限于数组
代码演示
var arr =["孙悟空","猪八戒","沙和尚"]
var arr1 =["牛魔王","铁扇公主","红孩儿"]
var result =arr.concat(arr1);//连接2个
console.log(result);
var arr2 =["超神","热血","战斗"];
result =arr.concat(arr1,arr2,"好好学习",999);//连接多个数组,并且加入元素
console.log(result);
join()
- 该方法可以将数组转换为一个字符串
- 该方法不会对原数组产生影响,而是将转换后的字符串作为结果返回
- 在join()中可以指定一个字符串作为参数,这个字符串将会成为数组元素的连接符,如果不指定连接符,则默认使用,作为连接符
代码演示
var arr =["孙悟空","猪八戒","沙和尚"];
var result =arr.join("-");
console.log(result);
sort()
可以用来对数组中的元素进行排序,会影响原数组,默认会按照Unicode编码进行排序
即使对于纯数字的数组,使用sort()排序时,也会按照Unicode编码来排序,所以对数字排序时,可能会得到错误的结果
我们可以自己来指定排序的规则,我们可以在sort()添加一个回调函数,来指定排序规则,回调函数中需要定义两个形参,浏览器将会分别使用数组中的元素作为实参去调用回调函数,使用哪个元素不确定,但是肯定的是数组a一定排在数组b前边
- 浏览器会根据回调函数的返回值来决定元素的顺序
- 如果返回一个大于0的值,则元素会交换位置
- 如果返回一个小于0的值,则元素位置不变
- 如果返回一个0,则认为两个元素相等,也不交换位置
技巧:如果需要升序排列,则返回a-b;如果需要降序排列,则返回b-a!
var arr =[12,1,52,123];arr.sort(function (a, b) {return a-b;// if(a>b){// return 1;// }else if(a<b){// return -1;// }else {// return 0;// }})console.log(arr);
7.1.5、数组的遍历
for循环
for (var i = 0; i < arr.length; i++) {console.log(arr[i]);}
forEach()
一般我们都是使用for循环去遍历数组,JS还未我们提供了一个方法,用来遍历数组forEach()
注意:这个方法值支持IE8以上浏览器,IE8及以下浏览器均不支持该方法,使用如果需要兼容IE8,则不要使用forEach。
- forEach()方法需要一个函数作为参数
- 像这种函数,有我们创建,但不由我们调用,我们传进为回调函数数组中有几个元素,函数就会执行几次,每次执行时,浏览器会将遍历到的元素以实参的形式传递进来,我们可以来定义形参,来读取这些内容。
- 浏览器会在回调函数中传递三个函数:
- 第一个参数:就是当前正在遍历的元素
- 第二个参数:就是当前正在遍历元素的索引
- 第三个参数:就是正在遍历的数组
7.2、Date对象
在JS中使用Date对象来表示一个时间
//如果直接使用构造函数创建一个Date对象,则会封装为当前代码执行的时间
var date =new Date();
console.log(date);//Sun Nov 21 2021 11:36:41 GMT+0800 (中国标准时间)//创建一个指定时间的对象
//需要在构造函数中传递一个时间的字符串作为参数
//日期格式:月份/日/年/ 时:分:秒
var date1 =new Date("1/13/1999 05:03:03");
console.log(date1);//Wed Jan 13 1999 05:03:03 GMT+0800 (中国标准时间)//getDate()
//获取当前日期对象是几号
var date2 = date.getDate();
console.log(date2);//getDay:获取当前日期对象是几号
//会返回一个0-6的值
//0 表示 周日
// 1 表示 周一
var day =date.getDay();
console.log(day);//getMonth()
//获取当前时间对象的月份
//会返回一个0-11的值【所以我们在使用的时候一般给他加1】
// 0 表示 1月
// 1 表示 2月
//11 表示 12月
var month =date.getMonth();
console.log(month);//getFullYear()
//从Date对象返回四位数字返回年份
var year =date.getFullYear();
console.log(year);/*getTime()
获取当前日期对象的时间戳
-时间戳,指的是从格林威治标准时间的 1970年1月1日 0时0分0秒到当前日期所花费的毫秒数(1秒=1000毫秒)
-计算机在底层保存时间都是使用时间戳*/
var date4 =date.getTime();
console.log(date4);//获取此代码运行时的时间戳
var date3 =Date.now();
console.log(date3);
7.3、Math工具类
- Math和其他的对象不同,它不是一个构造函数;它属于一个工具类,不用创建对象,它里边封装了数学运算相关的属性和方法
abs()可以用来计算一个数的绝对值
console.log(Math.abs(-1));//1
ceil()可以对一个属进行向上取整,小数位只有有值就自动进1
console.log(Math.ceil(1.1));//2
floor()可以对一个数进行向下取整,小数部分会被舍掉
console.log(Math.floor(1.6));//1
round可以对一个数进行四舍五入
console.log(Math.round());//对一个数进行四舍五入
random()
- 可以用来生成一个0-1之间的随机数
- 生成一个0-X之间的随机数
Math.round(Nath.random()*X);
- 生成一个X-Y之间的随机数
Math.round(Math.random()*(y-x)+x);
pow(x,y)返回x的y次幂
console.log(Math.pow(2,2));//4
sqrt()用于对一个开发运算进行
console.log(Math.sqrt(4));//2
7.5、包装类
基本数据类型:
String Numnber Boolean Null Undefined
引用数据类型:
Object
在JS中为我们提供了三个包装类,通过这是三个包装类科银酱基本数据类型转换为对象
-
String()
- 可以将基本类型的字符串转换为String对象
-
Number()
- 可以将基本数据类型的数字转换为Number对象
-
Boolean()
- 可以将基本数据类型的布尔值转换为Boolean对象
注意:我们在实际应用中不会使用基本数据类型的对象,如果使用了基本数据类型的对象,在做一些比较时可能会带来一些不可预期的结果。比如,你创建一个布尔值为false的对象,放进去判断,结果因为对象强转成布尔值时,为true;最后也运行出来了!
- 方法和属性只能添加给对象,不能添加给其他基本数据类型,当我们对一些基本数据类型的支调用属性和方法时,浏览器会临时使用包装类将其转换为对象,然后再调用对象的属性和方法,调用完以后,再将其转换为基本数据类型。
- 【所以,我们用基本数据类型去调方法也可以】
7.6、String对象常用方法
String底层使用字符数组存储的,使用数组有的,他一般也有!String的方法基本都不会对它原数组造成影响!
charAt()可以返回字符串中指定位置
var str ="Hello lizhiming";
console.log(str.length);//15
console.log(str.charAt(2));//与str[2]返回一样
charCodeAt()获取指定位置字符的字符编码(Unicode编码)
console.log(str.charCodeAt(0));//72
String.formaCharCode()可以根据字符编码去获取字符
var str1 =String.fromCharCode(72);//H
concat()
- 可以用来连接两个和多个字符串
- 作用和
+号
差不多
var result =str.concat("你好","再见");console.log(result)
indexof()
- 该方法可以检索一个字符串中是否含有指定内容
- 如果字符串中有该内容,则会返回其第一次出现的索引
- 如果没有找到指定内容就返回-1
- 可以放置第二哥参数,指定开始查找的位置
var str ="hello lizhiming";var a =str.indexOf("h");console.log(a);
var b =str.indexOf("h",3);//从索引三位置开始寻找console.log(b);
lastIndexOf
- 该方法的用法和indexof()的用法一样
- 不同的时indexof是从前往后找,而这个是从后往前找
- 这个也可以指定开始查找位置
slice()
-
可以从字符串截取指定内容
-
不会影响字符串,而是将截取到的内容返回
-
参数:
-
第一个:开始位置(包括)
-
第二个:结束位置(不包括)
- 也可以省略第二个参数,则会截取到后边所有
-
也可以传递一个负数作为参数,负数的话将会从后变计算
- -1 倒数第一个
- -2 倒数第二个
-
substring()
- 可以用来截取一个字符串,和slice()类似
- 不同的是:
- 这个方法不能接收负值作为参数,如果传递了一个负值,则默认使用0
- 而且他还自动调整参数的位置,如果第二个参数小于第一个,则自动交换
var a = str.substring(0,5);console.log(a);
substr()谨慎使用
-
用来截取字符串
-
参数:
- 截取开始位置的索引
- 截取的长度
-
ECMAscript没有对该方法进行标准化,因此反对使用它
拓展:substr与substring:
js中substr和substring都是截取字符串中子串,非常相近,可以有一个或两个参数。
语法:substr([start ,length]) 第一个字符的索引是0,start必选 length可选
substring([start , end]) 第一个字符的索引是0,start必选 end可选
相同点:当有一个参数时,两者的功能是一样的,返回从start指定的位置直到字符串结束的子串
var str = "hello Tony";str.substr(6); //Tonystr.substring(6); //Tony
不同点:有两个参数时
(1)substr(start,length) 返回从start位置开始length长度的子串
“goodboy”.substr(1,6); //oodboy
【注】当length为0或者负数,返回空字符串
(2)substring(start,end) 返回从start位置开始到end位置的子串(不包含end)
“goodboy”.substring(1,6); //oodbo
【注】:
(1)substring 方法使用 start 和 end 两者中的较小值作为子字符串的起始点
(2)start 或 end 为 NaN 或者负数,那么将其替换为0
split()
- 可以将一个字符串拆分为一个数据
- 参数:
- 需要一个字符串作为参数,将会根据该字符串去拆分数组
8、正则表达式
正则表达式用于定义一些字符串的规则
- 计算机可以根据正则表达式,来检查一个字符串是否符合规则
- 获取将字符串中符合规则的内容提取出来
语法:
var 变量 =new RegExp("正则表达式","匹配模式");
// 使用typeof检查正则对象,会返回object
var reg =new RegExp("a");
//这个正则表达式可以来检查一个字符串中是否含有a【严格区分大小写】
//在构造器中可以传递一个匹配模式作为第二个参数
//可以是
//i 忽略大小写
//g 全局匹配模式
正则表达式的方法:
test()
-
使用这个方法可以用来检查一个字符串是否符合正则表达式的规则
-
如果符合则返回true,否则返回false
reg.test(str)
var reg =new RegExp("a|b","i"); var boo =reg.test("B"); console.log(boo);
8.1、正则表达式字面量方式
使用字面量来创建正则表达式
语法:var 变量 =/正则表达式/匹配模式
使用字面量的方式创建更加简单,但使用构造函数创建更加灵活。
[]
/*[]里的内容也是或的关系[ab] == a| b[a-z] 任意小写字母[A-Z] 任意大写字母[0-9] 任意数字[A-z] 任意字母,忽略大小写*/
var reg2 =/[0-9]/;
var boo2 =reg2.test("3854");
console.log(boo2);
[^]除了
var reg3 =/[^a-z]/;
var boo3 =reg3.test("3854");//true
var boo3 =reg3.test("a");//false
console.log(boo2);
console.log(boo3);
- 注意:
var reg4 =/a[ecd]g/;//aeg | acg| adg
8.2、字符串&正则表达式
split()
- 可以将一个字符串拆分为一个数组
- 方法中可以传递一个正则表达式作为参数,这样方法将会根据正则表达式去拆分字符串
- 这个方法即使不指定全局匹配,也会全都拆分
var str = "1a2b3c4d5f6g7h8j9k10";var result =str.split(/[A-z]/);console.log(result);
search()
- 可以搜索字符串中是否含有指定内容
- 如果搜索到指定内容,则会返回第一次出现的索引,如果没有收索到返回-1
- 它可以接受一个正则表达式作为参数,然后回根据正则表达式去检索字符串
serach()
只会查找第一个,即使设置全局匹配也没用
var str ="hello zhen chun i love you";
var result =str.search(/[zc]h/);
console.log(result);
match()
- 可以根据正则表达式,从一个字符串中将符合条件的内容提取出来
- 默认情况下我们的
match
只会找到第一个符合要求的内容,找到以后就停止检索 - 我们可以设置正则表达式为全局匹配,这样就会匹配到所有的内容(使用了“g”标识符或者设置它了的global属性值为ture时,那么新创建的正则表达式对象将使用模式对要将要匹配的字符串进行全局匹配)
- 可以为正则表达式设置多个匹配模式,且顺序无所谓
match()
会将匹配到的内容封装到一个数组中返回,即使只查询到一个结果。
var str = "1a2b3c4d5f6g7h8j9k10";
var result =str.match(/[a-z]/gi);
console.log(result);
-
replace()
-
可以将字符串指定内容替换新的内容
-
参数
- 被替换的内容,可以接收一个正则表达式作为参数
- 新的内容
-
默认只会替换第一个,所以当你想全替换的时候,可以使用全局匹配
-
var str = "1a2a3c4a5a6A7A8a9a10";var result =str.replace(/a/ig,",");//如果你没有传第二个参数进去,那就是undefined把a替换了!console.log(result);
8.3、正则表达式语法1
-
量词
-
通过量词可以设置一个内容出现的次数
-
量词只对它前边的一个内容起作用
-
{n}
至少出现n次 -
{m,n}
出现m到n次 -
{m,}
m次以上 -
+
至少一个,相当于{1,}
-
*
0个或多个,相当于{0,}
-
?
0个或1个,相当于{0,1}
-
-
var reg =/a{3}/;//至少出现3次var str ="aaaa";var result= reg.test(str);console.log(result);var reg1 =/a{1,3}/;//出现1次到3次var str1 ="aaaa";var result1= reg1.test(str1);console.log(result1);var reg3 =/a+/;//相当于{1,},一般用“x+”这种方式var str3 ="aaaa";var result3 =reg3.test(str3);console.log(result3);var reg4 =/a*/;//0个或多个var str4 ="b";var result4 =reg4.test(str4);console.log(result4);//truevar reg5 =/a?/;//0个到1个
var str5 ="aaaaaaa";
var result5 =reg5.test(str5);console.log(result5);
检查一个字符串的开头语结尾
-
^
表示开头 -
$
表示结束
var reg =/^a/;//a字开头
var str =“abaaabb”;
var result1 =reg.test(str);
console.log(result1);
var reg1 =/a$/;var str1 ="bbbba";var result2 =reg1.test(str1);console.log(result2);
注意:如果在正则表达式同时使用^ $
则要求字符串必须完全符合正则表达式
var reg2 =/^a$/;//这种情况下下只有a才是true,aa都是false
var reg3 =/^a|a$/;//这种情况才是以a开头,以a结尾
var str2 ="a";
var result3 =reg2.test(str2);
console.log(result3);
8.3、正则表达式语法2
-
\w
- 任意字符、数字、_ (相当于[A-z 0-9 _])
-
\W
- 除了字母、数字、_ ([ ^A-z 0-9 _ ])
-
\d
- 任意的数字[0-9]
-
\D
- 除了数字 [ ^0-9 ]
-
\s
- 空格
-
\S
- 除了空格
-
\b
- 单词边界
-
\B
- 除了单词边界
var str =prompt("请输入")
str =str.replace(/^\s*| s*$/g,"");//去掉前尾空格
console.log(str);
9.DOM简介
9.1、DOM查询
-
DOM,全称Document Object Model 文档对象
-
JS通过DOM来对HTML文档进行操作。只要理解了DOM就可以随心所欲的操作WEB页面
-
文档
- 表示就是整个HTML网页文档
-
对象
- 对象表示将网页中的每一部分都转换为了一个对象
-
模型
- 使用模型来表示对象之间的关系,这样方便我们获取对象
9.1.1基本知识
节点
- 节点Node 构成HTML文档最基本的单元
- 常用节点为四类
- 文档节点:整个HTML文档
- 元素节点:HTML文档中的HTML标签
- 属性标签:元素的标签
- 文本节点:HTML标签中的文本内容
节点的属性
【这个是我看尚硅谷截取过来的图片,好评尚硅谷,如果有侵权,告知我删了哈!那个水印我不知道怎么去】
获取元素节点
-
getElementById()
- 通过id属性获取一个元素节点对象
-
getElementsByTagName()
- 通过标签名获取一组元素的对象
- 这个方法会给我们返回一个类数组对象,所有查询的元素都会封装到对象中
- 即使查询到的元素只有一个,也会封装到数组中返回
-
getElentsByName()
- 通过name属性获取一组元素节点对象
-
innerHTML
-
用于获取元素内部的HTML代码的,对于自结束的标签,这个属性没有意义
-
如果需要读取元素的节点属性,直接使用元素.属性名
-
eg:
- 元素.id 元素.name 元素.value
-
注意:class属性不能采用这种方式,读取class属性时需要使用元素.className
-
元素节点的子节点
-
getElementsByTagName()
- 方法,返回当前节点的所有子节点
-
childNodes
-
属性,表示当前节点的所有子节点
-
根据DOM,标签之间的空白也会当成文本节点
-
注意:在IE8及以下的浏览器中,不会将空白文档当成子节点,所以该属性在IE8中会返回4哥子元素而其他浏览器是9个
-
-
children
- 属性,可以获取当前元素的所有子元素【推荐】
-
firstChild
- 属性,表示当前节点的第一个子节点
-
firstElementChild
- 获取当前元素的第一个子元素
- 不支持IE8以下的浏览器,如果需要兼容他们尽量不要使用
-
lastChild
- 属性,表示当前节点的最后一个子节点
获取父节点和兄弟节点
-
通过具体的节点调用
-
parentNode
- 属性,表示当前节点的父节点
-
previousSibling
- 属性,表示当前节点的前一个人兄弟节点
- 可能获取到空白的文本
-
nextSibling
- 属性,表示当前节点的后一个兄弟节点
-
innerText
- 该属性可以获取元素的文本内容
- 它和
innerHTML
类似,不同的是它会自动将html去除
-
previousElementSibling
- 获取前一个兄弟 元素,IE8及以下不支持
9.1.2、查询剩余属性、方法
-
body
- 属性,在document中有一个body属性,它保存的是
body
的引用
- 属性,在document中有一个body属性,它保存的是
-
documentElement
- 此属性为document的属性,保存的是
html
根标签
- 此属性为document的属性,保存的是
-
all
- 此属性为document的属性,代表页面的所有元素
-
getElementByClassName()
- 可以根据
class
属性获取一组元素节点对象 - 该方法不支持IE8
- 可以根据
-
querySelector()
- 需要一个选择器的字符串作为参数,可以根据一个CSS选择器来查询一个元素节点对象
- 虽然IE8中没有
getElementsByClassName()
,但是可以使用querySelector()
代替 - 使用该方法总会返回唯一的元素,如果满足条件的元素有多个,那它只会返回第一个
-
querySelectorAll()
- 该方法和querySelector()用法类似,不同的是它会将符合条件的元素封装到一个数组中返回
- 即使符合条件的元素只有一个,它会返回数组
代码实现
script>window.onload=function (){var all =document.all;console.log(all.length);var query =document.querySelector("#box div");console.log(query.innerHTML);var query1 =document.querySelectorAll("#box");console.log(query1);var de =document.documentElement;console.log(de);var body =document.body;console.log(body);};
9.2、DOM删除
removeChild()
删除子节点
confirm()
用于弹出一个带有确认和取消按钮的提示框,需要一个字符串作为参数,改字符串将会作为提示文字显示出来,如果用户点击确认会返回true,果果点击取消返回false
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>添加删除记录练习</title>
<link rel="stylesheet" type="text/css" href="css.css" />
<script type="text/javascript">function deleteA(){var tr = this.parentNode.parentNode;//获取要删除的员工的名字//var name = tr.getElementsByTagName("td")[0].innerHTML;var name = tr.children[0].innerHTML;//删除之前弹出一个提示框/** confirm()用于弹出一个带有确认和取消按钮的提示框* 需要一个字符串作为参数,该字符串将会作为提示文字显示出来* 如果用户点击确认则会返回true,如果点击取消则返回false*/var flag = confirm("确认删除"+name+"吗?");//如果用户点击确认if(flag){//删除trtr.parentNode.removeChild(tr);}/** 点击超链接以后,超链接会跳转页面,这个是超链接的默认行为,* 但是此时我们不希望出现默认行为,可以通过在响应函数的最后return false来取消默认行为*/return false;};window.onload = function(){//获取所有额超链接var allA = document.getElementsByTagName("a");//为每个超链接都绑定一个单击响应函数for(var i=0 ; i < allA.length ; i++) {allA[i].onclick = deleteA;}var addEmpButton =document.getElementById("addEmpButton");addEmpButton.onclick =function (){var empName =document.getElementById("empName").value;var email =document.getElementById("email").value;var salary =document.getElementById("salary").value;// var a =document.createElement("a");// a.innerText ="Delete";var tr =document.createElement("tr");// var nameTd =document.createElement("td");// var emailTd =document.createElement("td");// var salaryTd =document.createElement("td");// var aTd =document.createElement("td");tr.innerHTML ="<td>"+empName+"</td>"+"<td>"+email+"</td>"+"<td>"+salary+"</td>"+"<td><a href='javascript:;'>Delete</a></td>";var a =tr.getElementsByTagName("a")[0];//哪怕只有一个元素,该方法也会返回一个集合a.onclick =deleteA;// var nameText =document.createTextNode(empName);// var emailText =document.createTextNode(email);// var salaryText =document.createTextNode(salary);// var delText =document.createTextNode("delete");////// // a.appendChild(delText);上面有innerText// a.href ="javascript:;";// aTd.appendChild(a);// nameTd.appendChild(nameText);// emailTd.appendChild(emailText);// salaryTd.appendChild(salaryText);//// tr.appendChild(nameTd);// tr.appendChild(emailTd);// tr.appendChild(salaryTd);// tr.appendChild(aTd);var employeeTable =document.getElementById("employeeTable");var tbody =employeeTable.getElementsByTagName("tbody")[0];tbody.appendChild(tr);};};</script>
</head>
<body><table id="employeeTable"><tr><th>Name</th><th>Email</th><th>Salary</th><th> </th></tr><tr><td>Tom</td><td>tom@tom.com</td><td>5000</td><td><a href="javascript:;">Delete</a></td></tr><tr><td>Jerry</td><td>jerry@sohu.com</td><td>8000</td><td><a href="deleteEmp?id=002">Delete</a></td></tr><tr><td>Bob</td><td>bob@tom.com</td><td>10000</td><td><a href="deleteEmp?id=003">Delete</a></td></tr></table><div id="formDiv"><h4>添加新员工</h4><table><tr><td class="word">name: </td><td class="inp"><input type="text" name="empName" id="empName" /></td></tr><tr><td class="word">email: </td><td class="inp"><input type="text" name="email" id="email" /></td></tr><tr><td class="word">salary: </td><td class="inp"><input type="text" name="salary" id="salary" /></td></tr><tr><td colspan="2" align="center"><button id="addEmpButton" value="abc">Submit</button></td></tr></table></div></body>
</html>
注意:
for循环会在页面加载完成之后立即执行,而响应函数会在超链接被点击时才执行,当响应函数执行时,for循环早已执行完毕
9.3、操作样式
9.3.1、操作内联样式
通过JS修改的样式:
语法:元素.style.样式名 =样式值
注意:
- 如果CSS的样式中含有
-
,这种名称在JS中式不合法的,比如:background-colo
r需要将这种样式名改为驼峰命名法,去掉-
,然后将-
后的字母大写 - 通过style属性设置样式都是内联样式,而内联样式有较高的优先级,所以通过JS修改的样式往往会立即显示
- 但是如果在样式中写了
!important
,则此时样式会有最高的优先级,即使通过JS也不能覆盖该样式,此时将会导致JS修改样式失效,所以尽量不要为样式添加!important - 通过style属性设置和读取内联样式
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>操作内联样式</title><style>#box {width: 100px;height: 100px;background-color: red;}</style><script>window.onload = function () {var button = document.getElementById("button");button.onclick = function () {box.style.width = "300px";box.style.height = "300px";box.style.backgroundColor = "yellow";};var button1 = document.getElementById("button1");button1.onclick = function () {alert(box.style.width);alert(box.style.height);alert(box.style.backgroundColor);};};</script>
</head><body>
<div id="box"></div>
<button id="button">点我一下</button>
<button id="button1">查看内联样式</button>
</body>
</html>
9.3.2、获取元素当前显示样式
currentStyle
语法:元素.currentStyle.样式名
它可以用来读取当前正在显示的样式,如果当前元素没有设置该样式,则获取它的默认值
提示:只有IE支持,其他浏览器不支持
getComputedStyle() 推荐
这个方法来获取元素当前的样式,这个方法是window的方法,可以直接使用,需要两个参数
- 第一个:要获取的样式的元素
- 第二个:可以传一个伪参数,一般传null
该方法会返回一个对象,对象中封装了当前元素对应的样式(属性),可以通过对象.样式名
来读取样式,如果获取的样式没有设置,则会获取到真实的值,而不是默认值,比如:没有设置width,它不会获取到auto,而是一个长度,但是该方法不支持IE8及以下的浏览器
通过currentStyle
和和getComputedStyle()
读取到的样式都是只读的,不能修改,如果要修改必须通过style属性
自定义函数实现获取元素当前显示样本
定义一个函数,用来获取指定元素的当前的样式
参数:obj 要获取样式的元素
name 要获取的样式名
/*** 这种思想常用来解决兼容性问题* @param obj 对象* @param name 字符串属性* @returns {*}*/
function getStyle(obj ,name){if(window.getComputedStyle){//这里最好加window. 因为不加的话,他就是变量,变量没找到会报错,下面就没有机会执行了,// 要是属性的话,是undefined,就转false,去执行else,不会报错了。return getComputedStyle(obj,null)[name];}else {return obj.currentStyle[name];}
}
9.3.3、其他样式操作的属性
clientWidth clientHeight
这两个属性可以获取元素的可见宽度于高度,这些【包括后面的】属性都是不带px的,返回都是一个数字,可以直接进行计算,会获取元素的高度和宽度,包括内容区和内边距,这些属性都是只读的,不能修改。
offsetWidth offsetHeight
获取元素整个宽度和高度,包括内容区、内边距和边框
alert(box.offsetWidth);
offsetParent
可以用来获取当前元素是的定位父元素
- 会获取离当前元素最近的开启了定位的祖先元素
- 如果所有的祖先元素都没有开启定位,则会返回body
var op =box.offsetParent
offsetLeft
当前元素相对于其定位父元素的水平
alert(box.offsetLest);
offsetTop
当前元素相对于其定位父元素的垂直偏移量
alert(box.offsetLeft)
scrollWitdth
scrollHeight
可以获取元素整个滚动区域的宽度和高度
alert(box.scrollWidth)
scrollLeft
可以获取水平滚动读条的距离
scrollTop
可以获取垂直滚动条滚动的距离
alert(box.scrollTop)
技巧:
scrollHeight -scrollTop == clientHeight
说明垂直滚动条到底了
scrollWidth - scrollLeft == clientWidth
说明水平滚动条到底了
代码演示
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>#box {width: 300px;height: 500px;background-color: green;overflow: auto;}</style><script>/*** 当垂直表单滚动到底时,使表单可选项可用* onscroll* 该事件会在元素滚动条滚动时触发*/window.onload = function () {var box = document.getElementById("box");var inputs = document.getElementsByTagName("input");box.onscroll = function () {if (box.scrollHeight - box.scrollTop == box.clientHeight) {/*** disabled属性设置一个元素是否可以* 如果true,则表示禁用* 如果使false,则表示启用* @type {boolean}*/inputs[0].disabled = false;inputs[1].disabled = false;}};};</script>
</head>
<body>
<div ><h3>注册</h3><p id="box">年少轻狂的岁月沉淀下来的是哪些再也回不到的过去,而总让人感叹的则是未能珍惜而失去的那些,但这些也恰恰是我们让你去体会的,因为年少轻狂的岁月,一生也只有一次。世间最珍贵的不是得不到或已失去的,而是现在能把握的。我们生活在一个复杂又充满无奈的世界,身上背负着太多太多的责任和使命,有时我们处理不当,就会不堪重负,难以忍受。最宽阔的是海洋,比海洋更宽阔的是天空,比天空更宽阔的是人的胸怀。当你紧握双手,里面什么也没有,当你打开双手,世界就在你手中。年少轻狂的岁月沉淀下来的是哪些再也回不到的过去,而总让人感叹的则是未能珍惜而失去的那些,但这些也恰恰是我们让你去体会的,因为年少轻狂的岁月,一生也只有一次。世间最珍贵的不是得不到或已失去的,而是现在能把握的。我们生活在一个复杂又充满无奈的世界,身上背负着太多太多的责任和使命,有时我们处理不当,就会不堪重负,难以忍受。最宽阔的是海洋,比海洋更宽阔的是天空,比天空更宽阔的是人的胸怀。当你紧握双手,里面什么也没有,当你打开双手,世界就在你手中。年少轻狂的岁月沉淀下来的是哪些再也回不到的过去,而总让人感叹的则是未能珍惜而失去的那些,但这些也恰恰是我们让你去体会的,因为年少轻狂的岁月,一生也只有一次。世间最珍贵的不是得不到或已失去的,而是现在能把握的。我们生活在一个复杂又充满无奈的世界,身上背负着太多太多的责任和使命,有时我们处理不当,就会不堪重负,难以忍受。最宽阔的是海洋,比海洋更宽阔的是天空,比天空更宽阔的是人的胸怀。当你紧握双手,里面什么也没有,当你打开双手,世界就在你手中。</p></div><input type="checkbox" disabled="disabled"/>已阅读协议,我一定遵守
<input type="submit" value="注册" disabled="disabled" />
</body>
</html>
总结:
在写这个的时候,我常常发现一个问题:
getElementsByName
与getElementsByTagName
区别:
前者获得名字name属性;后者为标签名
9.4、事件
9.4.1、事件
- 事件
- 就是文档或浏览器窗口中发生一些特定的交互瞬间
- JavaScript与HTML之间的交互是通过事件实现的
- 对于Web应用来说,有下面这些代表性事件:
- 点击按钮
- 将鼠标移动至某个元素的上方
- 按下键盘上某个键
- 关闭窗口
- ……
代码实现
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>事件</title>
</head>
<body>
<button id="btn">我是一个按钮</button>
<script>var btn=document.getElementById("btn");/*可以为按钮的对应事件绑定处理函数的形式来响应事件这样当事件被触发时,其对应的函数将会被调用*///绑定一个单击事件//想这种为单击事件绑定的函数,我们称为单击响应函数btn.onclick =function (){alert("你好帅!~~")};
</script>
</body>
</html>
注意:
浏览器在加载一个页面时,是按照自上而下的顺序加载的,读取到一行运行一行,如果将script标签写在页面是上面,在代码执行时,页面还没有加载,页面没有加载DOM对象会导致无法获取DOM 对象。
为了解决上述问题,可以引入onload
onload
事件会在整个页面加载完成之后才触发,为window绑定一个onload
事件,该事件对应的响应函数将会在页面加载完成之后执行,这样可以确保我们的代码执行的所有DOM对象加载完毕了!
9.4.2、事件对象
事件对象
当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递进响应函数,在事件对象中封装了当前事件相关的一切信息,比如:鼠标的坐标、键盘哪个键被按下、鼠标滚轮滚动 方向……
onmousemove
该事件将会在鼠标在元素中移动时被触发clientX
可以获取鼠标指针的水平位置clientY
可以获取鼠标指针的垂直坐标
注意:
在IE8,响应函数被触发时,浏览器不会传递事件对象,在IE8及以下的浏览器中,是将事件对象作为window对象的属性保存
代码演示
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>事件对象</title><style>#agrsDiv {width: 600px;height: 500px;border: solid;}#showDiv {width: 600px;height: 200px;border: solid;}</style><script>window.onload = function () {var agrs = document.getElementById("agrsDiv");var show = document.getElementById("showDiv");agrs.onmousemove = function (event) {event = event || window.event;var x = event.clientX;var y = event.clientY;show.innerHTML = "x=" + x + ",y =" + y;};};</script>
</head>
<body>
<div id="agrsDiv"></div>
<p></p>
<div id="showDiv"></div>
</body>
</html>
练习:div随鼠标移动
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title><style type="text/css">#box1{width: 100px;height: 100px;background-color: red;/** 开启box1的绝对定位*/position: absolute;}</style><script type="text/javascript">window.onload = function(){/** 使div可以跟随鼠标移动*///获取box1var box1 = document.getElementById("box1");//绑定鼠标移动事件document.onmousemove = function(event){//解决兼容问题event = event || window.event;//获取滚动条滚动的距离/** chrome认为浏览器的滚动条是body的,可以通过body.scrollTop来获取* 火狐等浏览器认为浏览器的滚动条是html的,*/var st = document.body.scrollTop || document.documentElement.scrollTop;var sl = document.body.scrollLeft || document.documentElement.scrollLeft;//var st = document.documentElement.scrollTop;//获取到鼠标的坐标/** clientX和clientY* 用于获取鼠标在当前的可见窗口的坐标* div的偏移量,是相对于整个页面的* * pageX和pageY可以获取鼠标相对于当前页面的坐标* 但是这个两个属性在IE8中不支持,所以如果需要兼容IE8,则不要使用*/var left = event.clientX;var top = event.clientY;//设置div的偏移量box1.style.left = left + sl + "px";box1.style.top = top + st + "px";};};</script></head><body style="height: 1000px;width: 2000px;"><div id="box1"></div></body>
</html>
注意点:
document.onmousemove =function (event){};
为什么给onmousemove绑定的对象是整个文档呢,因为他是相对于整个文档来移动的。经常会把这个东西绑定给div,但这是错的,一但你的鼠标离开div的范围,那div就不会跟着它移动了。所有这个时候,它只能斜向下方向移动,所有我们针对的是整个文档页面,即为document。
- 滚条问题
var st =document.body.scrollTop || document.documentElement.scrollTop;
var sl =document.body.scrollLeft || document.documentElement.scrollLeft;
如果你没有加这两个,因为div的偏移量时相对于整个页面来说,
而clientX和clientY的偏移是对当前可见页面来说的,
当实际页面比当前页面要大,就会出现滚条,当你滑动滚条时,div会出现于鼠标分离的情况,就因为这两件事物偏移所对应的对象所不同,所有你必须让div的移动加上滚条的移动,就实现了对当前可见窗的移动了。
9.4.3、事件的冒泡
所谓的冒泡指的就是事件向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发
- 在开发中的大部分情况中,冒泡都是有用的,如果不希望发生事件冒泡可以通过事件对象来取消冒泡
cancelBubble
- 可以将事件对象的cancelBubble设置为true,即可取消冒泡
- true着取消,false则启用
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>事件的冒泡</title><style>#box{width: 500px;height: 500px;background-color: green;}span{width: 200px;height: 100px;background-color: yellow;}</style><script>window.onload =function (){var box =document.getElementById("box");box.onclick =function (event){event = event||window.event;alert("我是div函数");event.cancelBubble =true;};var span =document.getElementById("spanBox");span.onclick =function (event){event = event||window.event;alert("我是span函数");event.cancelBubble =true;};document.body.onclick =function (){alert("我是body函数");};};</script>
</head>
<body><div id="box">我是div<span id="spanBox">我是span</span></div>
</body>
</html>
9.4.4、事件的委派
我们希望,只绑定一次事件,即可应用到多分元素上,即使元素是后添加的,我们可以尝试将其绑定给元素的共同祖先元素。
事件的委派指将事件统一绑定给元素的共同祖先,这样当后代元素的事件被触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件。
事件的委派是利用了冒泡,通过委派可以减少事件的绑定次数,挺高程序性能。
target
event中的target表示的触发事件的对象
代码演示
<!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(){//创建一个livar li = document.createElement("li");li.innerHTML = "<a href='javascript:;' class='link'>新建的超链接</a>";//将li添加到ul中u1.appendChild(li);};/** 为每一个超链接都绑定一个单击响应函数* 这里我们为每一个超链接都绑定了一个单击响应函数,这种操作比较麻烦,* 而且这些操作只能为已有的超链接设置事件,而新添加的超链接必须重新绑定*///获取所有的avar 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(event.target.className == "link"){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>
9.4.5、事件的绑定
就目前而言,事件的绑定有三种
一:赋值绑定
window.onload = function () {var button = document.getElementById("button");button.onclick = function () {alert(1);};button.onclick = function () {alert(2);};
};
这种方式后者会对前者进行覆盖,所以它只会弹出2
二:addEventListener
addEvebtListener()
-
通过这个方法也可以为元素绑定响应函数
-
参数:
- 事件的字符串
- 回调函数,当时间触发时该函数会被调用
- 是否在捕获阶段触发事件,需要一个布尔值,一般情况下,都传
false
var button = document.getElementById("button");button.addEventListener("click", function () {alert(1);}, false);button.addEventListener("click", function () {alert(2);}, false);
优点:
- 可以同时为一个元素的相同事件同时绑定多个响应函数,这样当事件触发时,响应函数将会按照绑定的顺序执行
- 一些特定的事件也只能使用该方法绑定
缺点:
- 兼容性问题,IE8及以下没有这个方法
attachEvent()
- 在IE8中可以使用attachEvent()来绑定事件
- 参数:
- 事件的字符串,要on
- 回调函数
button.attachEvent("onclick",function (){alert(1);
});
button.attachEvent("onclick",function (){alert(2);
});
这个只有IE8及以下的时候采用,但我们考虑到兼容性问题,需要对浏览器做兼容-=》bind()函数
值得注意的是:
- 这个方法也可以同时为一个事件绑定多个处理函数
- 不同的是它是后绑定先执行,执行顺序和
addEventListener()
想反
9.4.6、bind()函数
定义一个函数,用来为指定元素绑定响应函数
addEventListener()
中的this,是绑定事件的对象
attachEvent()
中的this,是window
需要统一两个方法的this
- 参数:
- obj 要绑定事件的对象
- eventStr 事件的字符串(不要on)
- callback 回调函数
/**** @param obj 绑定事件的对象* @param eventStr 事件的字符串(不要on)* @param 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);});}}
9.4.7、事件的传播
关于事件的传播网景公司和微软有不同的理解
-
微软认为事件一个是由内向外传播,也就是当事件触发时,应该先触发当前元素上的事件,然后再向当前元素的祖先元素传播,也就说事情应该再在冒泡阶段执行
-
网景公司认为事件应该时由外向内传播的,也就是当事件触发时,应该先触发当前元素最外层的祖先元素,然后再向内传播给后代元素
-
W3C综合了两个公司的方案,将事件传播分成了三个阶段
-
捕获阶段
- 在捕获阶段时,从最外层的祖先元素向目标元素进行事件的捕获,但是默认此时不会触发事件
-
目标阶段
- 事件捕获到目标元素,捕获结束开始在目标元素上触发事件
-
冒泡阶段
- 事件从目标元素向他的祖先元素传递,依次触发祖先元素的事件
-
注意:
-
如果希望在捕获阶段就触发事件,可以将
addEventListener()
的第三个参数设置为true
-
IE8及以下的浏览器中没有捕获阶段
图示
代码演示
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>事件的传播</title><style>#box1{height: 300px;width: 300px;background-color: yellow;}#box2{height: 150px;width: 150px;background-color: green;}#box3{height: 100px;width: 100px;background-color: red;}</style><script>window.onload =function (){var box1 =document.getElementById("box1");var box2 =document.getElementById("box2");var box3 =document.getElementById("box3");bind(box1,"click",function (){alert("我是box1");});bind(box2,"click",function (){alert("我是box2");});bind(box3,"click",function (){alert("我是box3");});};function bind(obj,eventStr,callback){if(obj.addEventListener){//大部分浏览器//这里如果你把obj去掉,那么调用addEventListener的就是window,
// 如果是window调用的话那就是顺序调用了,只有是这个事件调用才是符合事件的传播 obj.addEventListener(eventStr,callback,false);}else {/*** this是由谁调的方式决定* callback().call(obj);*///IE8及以下浏览器obj.attachEvent("on"+eventStr,function (){callback.call(obj);});}}</script>
</head>
<body>
<div id="box1"><div id="box2"><div id="box3"></div></div>
</div>
</body>
</html>
注意:
这里如果你把obj
去掉,那么调用addEventListener
的就是window
,
如果是window
调用的话那就是顺序调用了,只有是这个事件调用才是符合事件的传播
9.4.8、拖曳
拖曳的流程
- 当鼠标在被拖曳元素上按下时,开始拖曳
onmousedown
- 当鼠标移动时被拖曳元素跟随鼠标移动
onmousemove
- 当鼠标松开时,被拖曳元素固定在当前位置
onmouseup
鼠标位置问题:
- 逻辑图解
- 代码演示
//div的偏移量 鼠标.clientX-box.offsetLeft;
//div的偏移量 鼠标.clientY-box.offsetTop;
var ol =event.clientX -box.offsetLeft;
var ot =event.clientY -box.offsetTop;var left =event.clientX-ol;var top =event.clientY-ot;box.style.left =left+"px";box.style.top =top+"px";
注意:
当我们拖曳一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,此时会导致拖曳功能异常,这个是浏览器所提供的默认行为,如果不希望发生这个行为,则可以通过return false
来取消默认行为
但是 这对IE8 不管用
针对IE8我们使用,捕获函数和释放捕获函数来解决
obj.setCapture&&obj.setCapture();//捕捉函数
obj.releaseCapture && obj.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*///获取box1var box1 = document.getElementById("box1");var box2 = document.getElementById("box2");var img1 = document.getElementById("img1");//开启box1的拖拽drag(box1);//开启box2的drag(box2);drag(img1);};/** 提取一个专门用来设置拖拽的函数* 参数:开启拖拽的元素*/function drag(obj) {//当鼠标在被拖拽元素上按下时,开始拖拽 onmousedownobj.onmousedown = function (event) {//设置box1捕获所有鼠标按下的事件/** setCapture()* - 只有IE支持,但是在火狐中调用时不会报错,* 而如果使用chrome调用,会报错*//*if(box1.setCapture){box1.setCapture();}*/obj.setCapture && obj.setCapture();event = event || window.event;//div的偏移量 鼠标.clentX - 元素.offsetLeft//div的偏移量 鼠标.clentY - 元素.offsetTopvar ol = event.clientX - obj.offsetLeft;var ot = event.clientY - obj.offsetTop;//为document绑定一个onmousemove事件document.onmousemove = function (event) {event = event || window.event;//当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove//获取鼠标的坐标var left = event.clientX - ol;var top = event.clientY - ot;//修改box1的位置obj.style.left = left + "px";obj.style.top = top + "px";};//为document绑定一个鼠标松开事件document.onmouseup = function () {//当鼠标松开时,被拖拽元素固定在当前位置 onmouseup//取消document的onmousemove事件document.onmousemove = null;//取消document的onmouseup事件document.onmouseup = null;//当鼠标松开时,取消对事件的捕获obj.releaseCapture && obj.releaseCapture();};/** 当我们拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,* 此时会导致拖拽功能的异常,这个是浏览器提供的默认行为,* 如果不希望发生这个行为,则可以通过return false来取消默认行为** 但是这招对IE8不起作用*/return false;};}</script>
</head>
<body>我是一段文字<div id="box1"></div><div id="box2"></div><img src="img/an.jpg" id="img1" style="position: absolute;"/>
</body>
</html>
9.4.9、鼠标滚轮事件
- 火狐滚轮
DOMMouseScroll
-
注意该事件需要通过
addEventListener()
函数来绑定 -
火狐不支持
wheelDelta
这个属性,其对应用的是detail
这个属性来获取滚动的方向,向上滚动-3
,向下滚动3
-
当滚轮滚动时,如果浏览器有滚动条,滚动条会随之滚动,这是浏览器的默认行为,一般用
reture false
,来取消,但是火狐是用addEventListener()
,使用addEventListener()方法来绑定响应函数,取消默认行为不能使用return false
。需要使用event来取消默认行为event.preventDefault,但是IE8对此又不支持,如果调用会直接报错,所以我们一般这样写:event.preventDefault && event.preventDefault()
- 其他浏览器
onwheel
wheelDelta
来获取滚轮方向,当向上滚动时,其返回值为120
,向下滚动时,其返回值为-120
- 用
returen false
来取消浏览器滚条随滚条移动的情况。
代码演示
<!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的divvar 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>
9.4.10、键盘事件
键盘事件
- 按键被按下
onkeydown
- 对于
onkeydown
来说如果一直按着某个按键不松手,则事件会被一直触发。 - 当
onkeydown
连续触发时,第一次和第二次之间的间隔稍微长一点,其他的会变得非常快,这种设计是为了防止误操作的发生
-
按键被松开
onkeyup
-
键盘事件一般会绑定给一些可以获取焦点的对象或者是document
-
keyCode
获取按键的unicode编码
通过它可以判断哪个按键被按下
altKey
判断alt键是否被按下ctrlKey
判断ctrl键是否被按下shiftKeY
判断shift是否被按下
练习:键盘移动div
- 相关知识
向左的unicode是37
向上的unicode是38
向右的Unicode是39
向下的unicode是40
- 代码演示
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>键盘移动div</title><style>#box{width: 100px;height: 100px;background-color: red;border: solid;position: absolute;}</style><script>window.onload =function (){/*** 37向左* 38向上* 39向右* 40向下*/var box =document.getElementById("box");document.onkeydown =function (event){event =event|| window.event;var speed =10;if(event.ctrlKey){speed =50;}switch (event.keyCode) {case 37:box.style.left =box.offsetLeft -speed +"px";break;case 38:box.style.top =box.offsetTop -speed+"px";break;case 39:box.style.left =box.offsetLeft +speed+"px";break;case 40:box.style.top =box.offsetTop+speed+"px";break;}};};</script>
</head>
<body>
<div id="box"></div>
</body>
</html>
10、BOM简介
BOM浏览器对象模型
- BOM可以使我们通过JS来操作浏览器
- 在BOM中提供了一组对象,用来完成对浏览器的操作
BOM对象
Window
代表的使整个浏览器的窗口,同时window也是网页中的全局对象
Navigator
代表的是当前浏览器的信息,通过该对象可以识别不同的浏览器
Location
代表的是当前浏览器的地址栏信息,通过Location可以获取地址栏信息,或者操作浏览器跳转页面
History
代表的是浏览器的历史记录,可以通过该对象来操作浏览器的历史记录,由于隐私原因,该对象不能获取到具体的历史记录,只能操作浏览器向前或向后翻页,而且该操作只在当次访问时才有效
Screen
代表用户的屏幕信息,通过该对象可以获取到用户的显示器的相关信息
注意:这些BOM对象在浏览器中都是作为window对象的属性保存的,可以通过window对象来使用,也可直接使用
10.1、Navigator
Navigator
代表的是当前浏览器的信息,通过该对象可以识别不同的浏览器,由于历史原因,Navigator对象中大部分属性都已经不能帮助我们识别浏览器了。
一般我们只会使用userAgent
来判断浏览器的信息,userAgent是一个字符串,这个字符串中包含用来秒速浏览器信息的内容,不同的浏览器有不同的userAgent。(userAgent等价于浏览器)
- 火狐的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(Edge)
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了
但“技高一尺,魔高一丈”,我们现在虽然不能通过userAgent不能判断,还可以通过一些浏览器中特有的对象,来判断浏览器的信息,比如**ActiveXObject
**
代码演示
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(Edge)")
}
这个只是初级的检测代码,在现在的开发过程中,也并没有起到作用,因为现在的Edge已经非常像Chrome了。
10.2、History
对象可以用来操作浏览器向前或向后翻转
length
属性,可以获取到当前访问的链接数量
back()
可以退回到上一个页面,作用和浏览器的回退按钮一样
forward()
可以跳转下一个页面,作用和浏览器的前进按钮一样
go()
可以用来跳转到指定的页面,需要一个整数作为参数
eg:
1:向前跳转一个页面,相当于forward()
2:向前跳转两个页面
-1:向后跳转一个页面,相当于back()
-2:向后跳转两个页面
代码演示
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>text1</title>
</head>
<body>
<a href="text2.html">去text2</a>
</body>
</html>
这个是test1
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>tex2</title><script>window.onload =function (){var butt =document.getElementsByTagName("button")[0];butt.onclick =function (){history.forward();}};</script>
</head>
<body>
<a href="historyEx.html">回到history</a>
<button>向前</button>
</body>
</html>
这个是text2
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>history</title><script>window.onload = function () {var butt = document.getElementsByTagName("button")[0];butt.onclick = function () {history.go(-2);}};alert(history.length);</script>
</head>
<body>
<button>后退</button>
</body>
</html>
这个是history
10.3、Location
location
该对象封装了浏览器的地址栏信息
-
如果直接打印location,则可以获取到地址栏的信息(当前页面的完整路径)
-
如果直接将location属性修改为一个完整的路径,或相对路径
则我们页面会自动跳转到该路径,并且会生成相应的历史记录
location ="https://www.bilibili.com/";
location ="https://v.qq.com/"
assign()
用来跳转到其他页面,作用和直接修改location
一样
location.assign("https://v.qq.com/");
reload()
- 用来使用一个新的页面替换当前页面,调用完毕也会跳转页面,不会生成历史记录,不能使用回退按钮
- 在括号内加入
true
即可强制清除缓存,不加则默认为普通的刷新
- 代码演示
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>LocationEx</title><script>
window.onload =function (){var butt =document.getElementsByTagName("button")[0];butt.onclick =function (){// location ="https://www.bilibili.com/";// location.assign("https://v.qq.com/");location.reload(true);};
};</script>
</head>
<body>
<button>点一下</button>
<input type="text">
</body>
</html>
10.4、定时器简介
如果希望一段程序,每间隔一段时间执行一次,可以使用定时调用
setInterval()
定时调用,可以将一个函数,每隔一段时间执行一次
参数:
- 回调函数,该函数会每隔一段时间被调用一次
- 每次调用间隔的时间,单位是毫秒
- 返回值:返回一个Number类型的数据,这个数字用来作为定时器的唯一标识。
clearInterval()
此方法需要一个定时器标识作为参数,这样来关闭对应的定时器
- 代码演示
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>定时器简介</title><script>window.onload = function () {var count = document.getElementById("count");var num = 1;var timer = setInterval(function () {count.innerHTML = num++;if (num == 11) {clearInterval(timer)}}, 1000)};</script>
</head>
<body>
<h1 id="count"></h1>
</body>
</html>
10.4.1 定时器练习
clearInterval()注意点
- clearInterval()可以接受任意参数
- 如果参数是一个有效的定时器的标识,则关闭该定时器
- 如果参数不是一个有效的标识,则什么也不做,也不会报错
其他注意点:
- 如果同一个元素上绑定了多个定时器,那记得每在开启一个的时候,关闭前一个(这个用来防备按了多次,导致切换速度快)
- 注意标识的范围
- 如果右多个相同类型而内容不同的数据,可以用数组来储存,方便操作
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>定时器练习</title><script>window.onload =function (){//获取img1标签以便修改它的src属性,来达到换图片的效果var img1 =document.getElementById("img1");//将图片封装到数组里,方便我们切换图片var imgArr =["./picture/1.JPG","./picture/2.bmp","./picture/3.bmp","./picture/4.png","./picture/5.jpg"];//数组下标索引var index =0;//定义定时器的标识,以便关闭定时器,// 如果你不在这里定义,而在按钮1中定义的话,按钮二范围内,它看不到这个标识var timer;//为butt1绑定单击响应函数var butt1 =document.getElementById("butt1");butt1.onclick =function (){/*** 目前,我们每点一次按钮,就会开启一个定时器* 点击多次就会开启多个定时器,这就导致图片切换的速度过快* 并且我们只能关闭最后一次定时器*///在开启定时器之前,需要将当前元素上的其他定时器关闭clearInterval(timer);//开启一个定时器来自动切换图片timer =setInterval(function (){index++;index =index%imgArr.length;//判断所以是否超过最大索引,将其置为0//修改img1的src属性,达到切换效果img1.src =imgArr[index];},1000);};var butt2 =document.getElementById("butt2");//为bttu2绑定一个单击响应函数butt2.onclick =function (){/*clearInterval()可以接受任意参数如果参数是一个有效的定时器的标识,则关闭该定时器如果参数不是一个有效的标识,则什么也不做,也不会报错*/clearInterval(timer);}}</script>
</head>
<body>
<img src="./picture/1.JPG" alt="图片" id="img1">
<br/><br/>
<button id="butt1">开始</button>
<button id="butt2">暂停</button>
</body>
</html>
10.4.2 div随键盘移动·改进
造成它开始动的那一下,会有些卡动的解决方法,是因为让onkeyCode控制了速度,它有个防误碰机制,所以我们定义一个定时器来控制div移动的速度。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>键盘移动div改进</title><style>#box {width: 100px;height: 100px;background-color: red;border: solid;position: absolute;}</style><script>window.onload = function () {var speed =10;var dir =0;//开启一个定时器来控制它移动的速度,不管它的方向,让onkeydown来只控制方向setInterval(function (){switch (dir) {case 37:box.style.left = box.offsetLeft - speed + "px";break;case 38:box.style.top = box.offsetTop - speed + "px";break;case 39:box.style.left = box.offsetLeft + speed + "px";break;case 40:box.style.top = box.offsetTop + speed + "px";break;}},30)var box = document.getElementById("box");document.onkeydown = function (event) {event = event || window.event;var speed = 10;if (event.ctrlKey) {speed = 50;}dir =event.keyCode;};document.onkeyup =function (){dir =0;speed =10;}};</script>
</head>
<body>
<div id="box"></div>
</body>
</html>
10.5、延迟调用
延迟调用:setTimeout()
延迟调用一个函数不马上执行,而是隔一段时间后再执行,而且只会执行一次
延迟调用和定时调用的区别:
- 延迟调用只会执行一次,而定时调用会执行多次
- 延迟调用和定时调用实际上可以互相代替,在开发中可以根据自己的需求去选择
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>延迟调用</title><script>window.onload =function (){var num =1;var timer =setTimeout(function (){console.log(num++);},5000)//使用clearTimeout来关闭一个延迟调用,因为这里关闭了,使用1不会出来clearTimeout(timer);};</script>
</head>
<body>
</body>
</html>
10.6、应用
10.6.1、定时器的应用
按钮移动div
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>按钮移动div</title><style>*{margin: 0;padding: 0;}#box {height: 100px;width: 100px;background-color: red;border: solid;position: absolute;left: 0;}</style><script>window.onload = function () {var box = document.getElementById("box");var butt = document.getElementsByTagName("button")[0];var timer;butt.onclick = function () {clearInterval(timer);timer = setInterval(function () {var oldValue = parseInt(getStyle(box, "left"));var newValue = oldValue + 10;if(newValue>1600){newValue =1600;}box.style.left = newValue + "px";if (newValue >= 1600) {clearTimeout(timer)}}, 30)};};function getStyle(obj, name) {if (window.getComputedStyle) {return getComputedStyle(obj, null)[name];} else {return obj.currentStyle[name];}}</script>
</head>
<body>
<button>点击按钮向右移动</button>
<br/><br/>
<div id="box"></div>
<div id="line" style="border: 1px solid;height: 10000px;width: 0px;position: absolute;left: 1600px; top: 0px"></div>
</body>
</html>
按钮移动div·进阶
- 提取方法
但是这个方法现在也是有安全隐患的,定时器的变量是全局变量,他们共用这个定时器,当你想两个事件同时进行的话,那便办不到,原因是你开启第二个事件的定时器时,第一个就被关闭了。
/*** 参数:* @param obj 要执行动画的对象* @param target 执行动画的目标位置* @param speed 移动的速度(正数向右移动,负数向左移动)*/function move(obj,target,speed){clearInterval(timer);var current =parseInt(getStyle(obj,"left"));/*判断速度的正负值如果从0向1600移动,speed为正如果从1600向0移动,则speed为负*/if(current>target){//此时速度应为赋值speed =-speed;}timer =setInterval(function () {var oldValue =parseInt(getStyle(obj,"left"));var newValue =oldValue+speed;//向左移动时,需要判断newValue是否小于target//向右移动时,需要判断newValue是否大于targetif(speed<0 && newValue<target || speed>0 && newValue>target){newValue =target;}obj.style.left =newValue+"px";if(newValue ==1600){clearInterval(timer)}},30)}
- 代码演示
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>按钮移动div·进阶</title><style>*{margin: 0;padding: 0;}#box{left: 0;height:100px ;width: 100px;position: absolute;border: solid;background-color: red;}</style><script>var timer;window.onload =function () {var butt1 =document.getElementsByTagName("button")[0];var butt2 =document.getElementsByTagName("button")[1];var box =document.getElementById("box");butt1.onclick = function () {move(box,800,10);};butt2.onclick =function (){move(box,0,10);};};/*** 参数:* @param obj 要执行动画的对象* @param target 执行动画的目标位置* @param speed 移动的速度(正数向右移动,负数向左移动)*/function move(obj,target,speed){clearInterval(timer);var current =parseInt(getStyle(obj,"left"));/*判断速度的正负值如果从0向1600移动,speed为正如果从1600向0移动,则speed为负*/if(current>target){//此时速度应为赋值speed =-speed;}timer =setInterval(function () {var oldValue =parseInt(getStyle(obj,"left"));var newValue =oldValue+speed;//向左移动时,需要判断newValue是否小于target//向右移动时,需要判断newValue是否大于targetif(speed<0 && newValue<target || speed>0 && newValue>target){newValue =target;}obj.style.left =newValue+"px";if(newValue ==1600){clearInterval(timer)}},30)}function getStyle(obj,name) {if(window.getComputedStyle){return getComputedStyle(obj,null)[name];}else {return obj.currentStyle[name];}}</script>
</head>
<body>
<button id="butt1">点击按钮向右移动</button>
<button id="butt2">点击按钮向左移动</button>
<br/><br/>
<div id="box"></div>
<div id="line" style="border: 1px solid;height: 10000px;width: 0px;position: absolute;left: 1600px; top: 0px"></div>
</body>
</html>
按钮变换div
- 提取方法到JS文件
这里的obj.timer避免了上处的安全隐患,且加入了回调函数,让此方法变得更加灵活,且将方向也作为形参传进去,让此方法适应性增强!
function getStyle(obj,name) {if(window.getComputedStyle){return getComputedStyle(obj,null)[name];}else {return obj.currentStyle[name];}
}/*** 参数* @param obj 要执行动画的对象* @param dir 要执行动画的样式;比如:left top width height* @param target 执行动画的目标位置* @param speed 移动的速度* @param callback 回调函数,这个函数将会再动画执行完毕以后执行*/
function move(obj,dir,target,speed,callback){//关闭上一个定时器clearInterval(obj.timer);var current =parseInt(getStyle(obj,dir));if(current>target){speed =-speed;}obj.timer =setInterval(function (){var oldValue =parseInt(getStyle(obj,dir));var newValue =oldValue+speed;if(speed<0 && newValue<target ||speed>0 && newValue>target){newValue =target;}obj.style[dir] =newValue +"px";if(newValue ==target){clearInterval(obj.timer);callback && callback();}},30)
}
- 代码演示
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>按钮演播div</title><style>*{margin: 0;padding: 0;}#box1{width: 100px;height: 100px;background-color: red;position: absolute;left: 0;border: solid;}#box2{width: 100px;height: 100px;background-color: yellow;position: absolute;left: 0;top:300px;border: solid;}</style><script src="tool.js"></script><script>window.onload =function () {var box1 = document.getElementById("box1");var box2 = document.getElementById("box2");var butt1 = document.getElementById("butt1");var butt2 = document.getElementById("butt2");var butt3 = document.getElementById("butt3");var butt4 = document.getElementById("butt4");butt1.onclick = function () {move(box1, "left", 1600, 20);}butt2.onclick = function () {move(box1, "left", 0, 10);}butt3.onclick = function () {move(box2, "left", 1600, 10);}butt4.onclick = function () {move(box2, "width", 1600, 10, function () {move(box2, "height", 800, 10, function () {move(box2, "top", 0, 10, function () {move(box2, "width", 100, 10, function () {confirm("漂亮吧!");});});});});};};</script>
</head>
<body>
<button id="butt1">点击按钮以后box1向右移动</button>
<button id="butt2">点击按钮以后box1向左移动</button>
<button id="butt3">点击按钮以后box2向右移动</button>
<button id="butt4">测试按钮</button><br /><br /><div id="box1"></div>
<div id="box2"></div><div id="line" style="position: absolute;width: 0;height: 1600px;left: 1600px;border: solid;top:0"></div>
</body>
</html>
10.6.2、轮播图功能实现
目前,这个,我还不是很会!
<!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宽度 520navDiv宽度 25*5 = 125520 - 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(){//获取imgListvar imgList = document.getElementById("imgList");//获取页面中所有的img标签var imgArr = document.getElementsByTagName("img");//设置imgList的宽度imgList.style.width = 520*imgArr.length+"px";/*设置导航按钮居中*///获取navDivvar navDiv = document.getElementById("navDiv");//获取outervar outer = document.getElementById("outer");//设置navDiv的left值navDiv.style.left = (outer.offsetWidth - navDiv.offsetWidth)/2 + "px";//默认显示图片的索引var index = 0;//获取所有的avar 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);//获取点击超链接的索引,并将其设置为indexindex = this.num;//切换图片/** 第一张 0 0* 第二张 1 -520* 第三张 2 -1040*///imgList.style.left = -520*index + "px";//设置选中的asetA();//使用move函数来切换图片move(imgList , "left" , -520*index , 20 , function(){//动画执行完毕,开启自动切换autoChange();});};}//开启自动切换图片autoChange();//创建一个方法用来设置选中的afunction setA(){//判断当前索引是否是最后一张图片if(index >= imgArr.length - 1){//则将index设置为0index = 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>
10.7、类的操作
类CSS修改
- 方式一:
box.style.width ="300px";
通过style属性来修改元素的样式,每修改一个样式,浏览器就需要重新渲染一次页面,这样的执行的性能是比较差,而且这种形式当我们要修改多个样式时,也不太方便
- 方式二:
box.className += " b2";
我们可以通过修改元素的class属性来简介的修改样式,这样一来,我们只需要修改一次,即可同时修改多个样式,浏览器渲染页面一次,性能比较好,并且这种方式,可以让表现和行为进一步分离。
方式三:提取方法
//定义一个函数,用来向一个元素中添加指定的class属性值
/** 参数:* obj 要添加class属性的元素* cn 要添加的class值* */
function addClass(obj , cn){//检查obj中是否含有cnif(!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");//删除classobj.className = obj.className.replace(reg , "");}/** toggleClass可以用来切换一个类* 如果元素中具有该类,则删除* 如果元素中没有该类,则添加*/
function toggleClass(obj , cn){//判断obj中是否含有cnif(hasClass(obj , cn)){//有,则删除removeClass(obj , cn);}else{//没有,则添加addClass(obj , cn);}}
- 代码演示:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>类的操作</title><style>*{margin: 0;padding: 0;}.b1{height: 100px;width: 100px;background-color: red;border: solid;}.b2{height: 300px;width: 300px;border: solid;}</style><script>window.onload =function () {var box =document.getElementById("box");var butt =document.getElementById("butt1");box.className +=" b2";butt.onclick =function (){// box.style.width ="300px";//方式二:// box.className +=" b2";// addClass(box,"b2");// removeClass(box,"b2");toggleClass(box,"b2");};};function addClass(obj,cn){if(!hasClass(obj,cn)){obj.className += " "+cn;}}function hasClass(obj,cn) {var reg =new RegExp("\\b"+cn+"\\b");return reg.test(obj.className);}function removeClass(obj,cn) {var reg =new RegExp("\\b"+cn+"\\b");obj.className =obj.className.replace(reg,"");}function toggleClass(obj,cn){if(hasClass(obj,cn)){removeClass(obj,cn)}else {addClass(obj,cn);}}</script>
</head>
<body>
<button id="butt1">点击修改div的类</button>
<br/><br/>
<div class="b1" id="box"></div>
</body>
</html>
11、JSON
JS中的对象只有JS自己认识,其他的语言都不认识,JSON就是一个特殊格式的字符串,这个字符串可以被任意的语言所识别,并且可以转换为任意语言中的对象,JSON再开发中主要用来数据的交互
JSON
javaScript Object Notation JS 对象表示法
JSON和JS对象的格式一样,只不过JSON字符串中的属性名必须加双引号,不然就会报错!其他的和JS语法一致!
JSON中允许的值 |
---|
1.字符串 |
2.数 组 |
3.布尔值 |
4. null |
5.对 象 |
6.数 组 |
创建JSON对象
var arr ='[1,2,3,"hello",true]';
var obj2 ='{"arr":[1,2,3]}';
var obj ='[{"name":"李白","age":18,"gender":"男",{"name":"美美","age":18,"gender":"女"}]';
转换
- JSON对象-》JS对象
将JSON字符串转换为JS中的对象,再JS中,为我们提供了一个工具类,就叫JSON,这个对象 可以帮助我们将JSON转换JS对象,也可以将一个JS对象转换为JSON
JSON.parse()
- 可以 将JSON字符串转换为JS对象
- 它需要一个JSON字符串作为参数,会将该字符串转换为JS对象并返回。
var obj ='[{"name":"李白","age":18,"gender":"男"},{"name":"美美","age":18,"gender":"女"}]';var jsObj =JSON.parse(obj);console.log(jsObj);
- JS对象-》JSON
JSON.stringify()
- 可以将一个JS对象装欢为JSON字符串
- 需要一个JS对象作为参数,会返回一个JSON字符串
var obj3 ={name:"李白",age:18,sex:"男"};var str =JSON.stringify(obj3);console.log(str);
值得注意的是:
JSON这个对象在IE7及以下的浏览器中不支持,所以再这些浏览器中调用时会报错。
eval()
- 这个函数可以用来执行一段字符串形式的JS代码,并将执行结果返回,但是如果使用
eval()
执行的字符串中含有{}
,它会将{}
当成是代码块,如果不希望将其当成代码块解析,则需要在字符串前后各加一个() eval()
这个函数的功能十分强大,可以直接执行一个字符串的JS代码,但是在开发中尽量不要使用,首先它的执行性能比较差,然后它害具有安全隐患。
那要怎么去兼容IE7及以下的浏览器呢!
直接引进JSON文件!~
完结
这是我看尚硅谷视频时所做的笔记,希望对大家有所帮助!谢谢!