目录
前言
开篇语
准备工作
认识BOM
概念
基本性质
延迟加载器
窗口尺寸
计时器
单次计时器
概念
注意事项
清除计时器
间歇计时器
概念
注意事项
清除计时器
案例
this指向window的元素
同步和异步
结束语
前言
开篇语
本系列博客主要分享JavaScript的基础语法知识,本期为第十期,主要讲解BOM相关重点知识点。
与HTML和CSS相比,JS加入了很多逻辑性的元素在里面,所以需要一定的逻辑思维能力,要求能够整合一些知识。如果遇到不理解之处,可以参阅同系列之前的章节。
准备工作
软件:【参考版本】Visual Studio Code
插件(扩展包):Open in browser, Live Preview, Live Server, Tencent Cloud AI Code Assistant, htmltagwrap
提示:在不熟练的阶段建议关闭AI助手
浏览器版本:Chrome
系统版本: Win10/11/其他非Windows版本
认识BOM
概念
JS中的几个核心概念——ES,DOM,BOM,目前我们已经接触了之前的两个,且目前为止我们所学的知识都属于基础阶段ecmascript的内容,后续进阶篇中我们会讲解ES6的内容。
BOM,全称为Browser Object Model,即浏览器对象模型,其核心对象为窗口(window)。
基本性质
window相当于我们的最高级节点,也就是根节点所在。
此前我们使用根节点一般是使用下面的方式——
document.documentElement
现在,我们只需要用一个window就可以代表上面的代码。
事实上,所有的DOM元素都是在window下的,比如我们的函数——
fn()
它实际上是下面代码的缩写形式——
window.fn()
同样的,又比如我们在控制台输出一个变量——
var a = 5
console.log(a)
实质上也是下面的代码的简写——
var a = 5
console.log(window.a)
就像DOM一样,BOM也可以绑定事件侦听器——
window.addEventListener("click", function () {
console.log(1)
})
延迟加载器
window.onload()方法相当于是一个延迟加载器,会把js延迟加载,延迟到DOM节点和图片,flash,css等加载完之后再执行。
window.DOMContentLoaded()是DOM加载完毕,不包含 图片,falsh,css 等就可以执行js加载,速度比onload()更快一些。
想要比较二者的执行速度,我们可以为一个按钮同时绑定onload和DOMContentLoaded事件,为了排除浏览器解析顺序的影响,我们先设置onload,后设置DOMContentLoaded——
window.addEventListener("load", function () {console.log(1);})window.addEventListener("DOMContentLoaded", function () {console.log(2);})
在控制台输出的效果如下——
窗口尺寸
window的 onresize 事件用于监听窗口变化的事件,当窗口的尺寸发生变化时,将会触发该事件。
如果想要得到BOM的实时尺寸的大小,可以使用window.innerWidth获取。
举个例子——
Q:我们现在有一个盒子,当我们缩减尺寸到一定程度时,隐藏盒子;反之,当尺寸增加到一定程度时,重新显示盒子。
A: 思路比较简单,首先让window绑定resize事件(事件侦听器里没有on),然后实时获取innerWidth,判定是否需要隐藏或者显示盒子。
盒子的初始样式略,JS代码如下——
var div = document.querySelector("div")window.addEventListener("resize", function () {if (window.innerWidth < 1000) div.style.display = "none"else div.style.display = "block"})
计时器
计时器由窗口window调用,其this指针指向window,是BOM的重要方法。
JS中的计时器主要有setTimeout和setInterval两种,分别用于单次延时调用和周期间歇调用,下面分别讲解这两种方法。
单次计时器
概念
单次计时器 setTimeout ,可以在间隔一定时间之后再调用回调函数。
使用setTimeout的基本方式如下——
var timer = window.setTimeout(回调函数, 延时时间)
其中timer代表当前的计时器,如果只是调用的话,可以不用写该变量,它的作用是便于我们之后清除计时器。
注意事项
-
window在调用的时候可以省略
-
延时时间单位是毫秒 但是可以省略,如果省略默认的是0
-
回调函数可以直接写 匿名函数(){...},也可以只写函数名,并在外部声明定义函数,最后,也可以用 '函数名()' 来写
-
页面中可能有很多的定时器,我们经常给定时器加标识符(名字)
清除计时器
我们的计时器在调用完之后,在内存中占用的空间依然存在,会严重消耗我们的内存。
因此,我们需要有一种清除机制,用于回收空间。
还记得我们之前保存的计时器变量timer吗,我们可以利用它来清除计时器——
clearTimeout(timer)
例如,我们可以绑定一个清除按钮,点击清理计时器——
var btn = document.querySelector("button")btn.onclick = function () {clearTimeout(timer)}
间歇计时器
概念
间歇计时器 setInterval ,用于设置间隔一定时间重复调用某一函数。
有时,仅仅延迟调用一次函数是不够的,因此我们常常使用 setInterval 来解决需要周期反复调用某一功能的需求。
比如,我们想要一个计时器每间隔一秒输出经过的时间,可以这么做——
var num = 0var timer = setInterval(function () {console.log(++num)}, 1000)
注意事项
大部分注意事项和setTimeout相同,但是尤其需要注意一点,setInterval是无限调用的,所以一定要设置时间间隔,否则会导致栈内存溢出。
清除计时器
方法和单次计时器类似——
clearInterval(timer)
案例
Q:实现一个时钟的功能,要求输出当前的年月日、时分秒。
示例效果如下——
A: 我们就假设目标时间为双十一吧。
思路其实也很简单,由于间歇计时器可以间隔一段时间调用一次回调函数,所以我们可以每隔一秒钟调用一次当前时间,然后用当前的时间对应的Date对象调用各时间参数即可。
参考CSS样式和HTML样式略,参考JS实现代码如下——
var timeBox = document.querySelector('.time-box')var typeBox = document.querySelector('.type-box')typeBox.innerHTML = '当前时钟'for (var i = 0; i < timeBox.children.length; i++) {timeBox.children[i].innerHTML = 88}function getNow() {var now = new Date()return [addZero(now.getFullYear()), addZero(now.getMonth() + 1), addZero(now.getDate()), addZero(now.getHours()), addZero(now.getMinutes()), addZero(now.getSeconds())]}function addZero(num) {return num >= 10 ? '' + num : '0' + num}var timer = setInterval(function () {for (var i = 0; i < timeBox.children.length; i++) {timeBox.children[i].innerHTML = getNow()[i]}}, 1000)
注意,当我们的时间返回值位数为一位时,我们需要为该参数的十位数补0。
Q:简单实现发送验证码后,间隔一定时间才能第二次发送验证码的功能,只需要完成发送按钮的功能即可,无需真正将验证码发送到指定手机。
示例效果如下——
A:CSS样式不需要调整,HTML代码略。
原理是利用间歇计时器,每隔一秒让剩余时间减一,在剩余时间到达0之前,将按钮的disabled值设置为false,并给出剩余时长的提示。
参考JS代码如下——
var btn = document.querySelector("button")var num = 5btn.addEventListener("click", function () {var temp = numthis.disabled = truethis.innerHTML = "再过" + temp + "秒重新发送短信"var timer = setInterval(function () {temp--btn.innerHTML = "再过" + temp + "秒重新发送短信"if (temp <= 0) {clearInterval(timer)btn.disabled = falsebtn.innerHTML = "发送"}}, 1000)})
值得注意的是,如果不设置临时变量temp,而直接操作num,则当按钮恢复为可点击状态后,num的初始值将是0,这将导致倒计时功能失效,故使用临时变量重置倒计时。
this指向window的元素
就目前所学知识而言,我们的this指针无非指向了三类元素——
- window
- Object实例化对象
- 事件源
其中,事件源也可以是window。
其他常见的this指向window的情况有——
1.命名函数
function fn() {
console.log(this);
}
fn()
2.匿名函数var fn1 = function () {
console.log(this);
}
fn1()
3.定时器
setTimeout(function () {
console.log(this);
})
4.立刻调用函数(声明后直接调用)
(function () {
console.log(this);
})()
同步和异步
JS代码在执行时,通常是先执行同步操作,后执行异步操作。
平时,我们看到的JS操作一般属于同步操作,直接由浏览器自行执行完毕了。
而那些需要人为干预或具有时间延迟的操作,基本属于异步操作。
常见的异步操作有——
- 事件
- 计时器
事件通常需要侦测元素的行为后才可以执行,所以是异步的;
计时器往往具有一定的时间延迟,所以同样是异步的。
同步操作之间的顺序通常取决于从上至下的浏览器解析顺序。
而异步操作之间的顺序,则取决于谁先满足事件发生的条件。
比如,对于下面的代码——
console.log(1);document.onclick = function () {console.log('2');}console.log(3);setTimeout(function () {console.log(4)}, 3000)
显然,控制台会先按顺序输出1和3,然后,如果我们在时延3秒之前点击了按钮,那么就是先输出2后输出4,否则就是先输出4后输出2。
结束语
本期的内容到这里就结束了,主要讲解了BOM的相关重点内容,这些在之后的面试中都是非常重要的。
在全栈领域,博主也只不过是一个普通的萌新而已。本系列的博客主要是记录一下自己学习的一些经历,然后把自己领悟到的一些东西总结一下,分享给大家。
文章全篇的操作过程都是笔者亲自操作完成的,一些定义性的文字加入了笔者自己的很多理解在里面,所以仅供参考。如果有说的不对的地方,还请谅解。
==期待与你在下一期博客中再次相遇==
——还在漏气的【H2O2】