JavaScript与BOM操作¶
约 1715 个字 119 行代码 预计阅读时间 7 分钟
BOM对象¶
在[BOM介绍]部分已经详细介绍了什么是BOM,这里不再赘述,下面主要介绍BOM中window对象的子对象:
- Navigator对象(
navigator):浏览器的对象,可以用来识别浏览器 - Location对象(
location):浏览器的地址栏信息 - History对象(
history):浏览器的历史记录,控制浏览器前进后退 - Screen对象(
screen):屏幕的信息
因为上面的对象都是window对象的子对象,所以可以直接调用,例如下面的代码:
| JavaScript | |
|---|---|
1 2 3 4 | |
后面的三个主题将简单介绍navigator、location和history对象的基本操作,详细的内容见对应的官方文档即可
Navigator对象¶
浏览器的对象,可以用来识别浏览器,一般会将其作为浏览器类型用于处理兼容性问题,例如官方提供的一段代码,用于判断用户的浏览器品牌和引擎
| JavaScript | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | |
Location对象¶
location表示的是浏览器地址栏的信息
location对象中有下面几个常见的属性和方法:
assign():将地址栏的地址修改为新的地址,参数传递一个网页地址字符串replace():使用新的地址替换已有的地址,参数传递一个网页地址字符串reload():刷新页面,参数可以传递一个true来强制清缓存刷新href:获取当前页面的地址值search:获取到地址栏的以?参数字符串,例如/en-US/docs/Location.search?q=123可以获取到?q=123,可以结合URLSearchParams类进一步提取参数值,参考官方文档
例如下面的代码:
| HTML | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 | |
| JavaScript | |
|---|---|
1 2 3 4 5 | |
History对象¶
History对象是浏览器的历史记录,控制浏览器前进后退,其常见的方法有:
back():返回上一个网页forward():返回下一个网页go():前往指定的网页。注意这个方法并不是直接传递一个表示网页地址的字符串,因为是history对象的方法,所以只能访问历史访问过的网站,并且是按照数值进行跳转,所以参数传递一个数值,正数表示前进指定个数的网页,负数表示后退指定个数的网页;如果参数传递0,则其效果与location对象的reload方法效果一样
定时器¶
前面简单了解了window对象的三个子对象,但是一般情况下不会经常使用这三个对象,所以做个了解即可,下面主要介绍BOM中重要的功能:定时器
定时器,就是控制某一个行为执行的时间,在BOM中,有两种设置定时器的方式:
-
setTimeOut():直接调用,该函数设置的定时器只能在指定的时间后执行一次回调函数中的代码,该函数有两个参数:- 第一个参数传递一个回调函数,回调函数中即为指定要执行的代码
- 第二个参数表示间隔时间(单位是毫秒),即多久之后执行回调函数中的代码
-
setInterval():直接调用,该函数设置的定时器可以在指定的时间间隔结束后执行若干次回调函数中的代码,该函数也有两个参数:- 第一个参数传递一个回调函数,回调函数中即为指定要执行的代码
- 第二个参数表示间隔时间(单位是毫秒),即间隔多久执行一次回调函数中的代码
介绍完设置定时器的方式,下面介绍关闭定时器的方式:
- 对于
setTimeOut()来说,关闭定时器需要利用到setTimeOut()函数的返回值,该函数返回值为计时器的序号,是一个数值类型,用于指定是哪一个计时器,将该返回值传递给clearTimeout()函数即可关闭指定的定时器 - 对于
setInterval()来说,关闭定时器需要利用到setInterval()函数的返回值,将该返回值传递给clearInterval()函数即可关闭指定的定时器
Note
需要注意,setInterval()函数不会考虑回调函数的执行时间,所以如果回调函数执行比较慢,那么setInterval()就无法保证每一次定时器的时间间隔是差不多的,之所以会出现这个问题见事件循环部分分析
setTimeOut()和clearTimeOut()基本使用如下:
| HTML | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 | |
| JavaScript | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 | |
setInterval()和clearInterVal()基本使用如下:
| HTML | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 | |
| JavaScript | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 | |
如果想使用setTimeOut()模拟setInterval()过程,可以在回调函数中使用setTimeOut()再开启一次定时器,为了避免开多个定时器,可以在开启下一个定时器前关闭前一个定时器,例如下面的代码:
| JavaScript | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
事件循环¶
在JavaScript中,和C/C++、Java一样,每一个函数在执行时都会进入一个调用堆栈,该堆栈最顶部就是正在执行的函数,最底部就是当前调用函数的最外层的函数。在JavaScript中,如果代码写在<script>标签中,则堆栈最底部就是<script>标签的作用域
但是在调用堆栈的函数都有一个特点,只有调用时才会进栈,一旦执行完就出栈,但是DOM中,对于各种事件的函数来说,并不能确定何时执行,如果某一个函数正在执行,事件的函数再加载到栈中就违反了「堆栈最顶部就是正在执行的函数」,因为被调用的函数还没有执行完
为了解决上面的问题,对于JavaScript中的函数来说,除了有一个调用堆栈的位置存储正在调用的函数以外,还有一个消息队列,一般事件触发的函数会先进入消息队列,如果调用堆栈此时有调用的函数还没有执行完,则事件触发的函数就会等待调用的函数结束执行再加载到调用堆栈中,否则会一直存储在消息队列中
而前面提到的定时器的本质就是利用消息队列,之所以使用setInterval()函数创建的定时器无法保证每一次间隔时间差不多是因为该函数只会根据上一次结束调用的时间计算间隔,间隔时间结束后就会将回调函数放入消息队列,如果当前调用堆栈有函数正在执行,则该回调函数就不会立刻执行
在官方文档中,也提到相关的问题:确保执行时间短于定时器时间间隔
在实际开发中,更推荐使用setTimeOut()和setTimeOut()模拟实现setInterval()
练习4¶
可以考虑完成(附加)DOM和BOM小练习