操作浏览器
BOM 是浏览器对象模型,包括 window (最高级的对象)、 loaction 、 navigation 和 document (即DOM)。因此, BOM 包含 DOM 。
定时器和延迟函数
延迟函数是 JavaScript 内置的一个用来让代码延迟执行的函数。
语法为:
let timer = setTimeout (回调函数, 等待的毫秒数)
延迟时间后执行一次,执行完后不再执行。
清除延时器的方式是先为延时器设置句柄,再使用语法将其删除。其语法如下:
clearTimeout(timer)
定时器是 JavaScript 内置的一个用来让代码自动一段时间后重复执行的函数。
语法为:
let timeId = setInterval (回调函数, 等待的毫秒数)
每隔一段时间便自动执行一次回调函数。
清除定时器的方式同上,为定时器设置句柄,再使用语法将其删除。其语法如下:
clearInterval(timeId)
注意,两个方法的清除方式可以混用,即方法 clearTimeout 可以清除定时器,方法 clearInterval 可用清除延时器,不会报错。
let timer = setTimeout(function() {
console.log('我是延时器');
}, 5000)
let timeId = setInterval(function() {
console.log('我是定时器');
}, 3000)
clearInterval(timer)
clearTimeout(timeId)
结果打印台没输出任何内容。
但是为了代码的理解性与健康性,建议对应使用方法来清除。
拓展:如何让延时器与定时器产生对方的效果。
根据上面所述,延时器只执行一次,定时器每隔一段时间就执行一次,如何让他们实现对方的效果,让定时器只执行一次,让延时器每隔一段时间就执行一次呢?
-
通过递归,让
setTimeout内部嵌套自身,执行完一次再执行,执行完后再执行······可以实现setInterval的效果。function test() { console.log('我是延时器'); setTimeout(test, 5000) } test()注意:
这里延时器内的函数
test后面不能跟括号,否则报错。因为这里的函数不是由我们程序员自己调用的,而是要延时器调用的,因此是回调函数,如果加了括号就变成立即执行函数,会自主调用到超出范围报错。
-
通过自清除,让
setInterval内部设置清除定时器的语句,让其执行第一次之后就被清除,可实现setTimeout的效果。let timeId = setInterval(function() { console.log('我是定时器'); clearInterval(timeId) }, 3000)
js 的执行机制
聊完定时器与延时器,接下来说说 js 的执行机制。
由于用户在操作浏览器页面的元素节点数据时只能单线程操作(即用户想要实现编辑与增加功能必须先编辑再添加或先添加再编辑,不能同一时间一边实现数据编辑一边实现数据添加),因此从一开始就决定了 javascript 是一个自上而下逐一执行的单线程代码。
但是根据我们的生活经验我们知道,如果一件事情没做完就等待那件事情做完再做下一件事情,效率十分低下,为了解决这个问题, javascript 提出了同步与异步的概念。
同步
同步即前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。
打个比方,妈妈出门前为你列了个清单,让你煮饭、做菜、洗衣服,同步执行的顺序是你先把生米放进电饭煲内煮饭,然后就坐在旁边干等,等他煮熟了再去做菜洗衣服。
但是这样极不合理。异步的概念就出来了。
异步
异步即在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。
还是同一个例子,妈妈让你煮饭、做菜、洗衣服,异步是检索这几个步骤,发现煮饭很花费时间,因此你把米洗好放进电饭煲按下开关让它煮饭,自己就可抽身去处理别的事情了。
在 javascript 中,异步任务又分为以下三种:
- 普通事件,如
click、resize等 - 资源加载,如
load、error等 - 定时器,包括
setInterval、setTimeout等
执行机制
- 先执行执行栈中的同步任务,异步任务(回调函数)放入任务队列中(任务队列也称为消息队列),由浏览器代替解析,解析完毕后按顺序放进任务队列内。
- 执行栈中所有同步任务执行完毕,系统会按次序读取任务队列中已执行完毕的异步任务,开始执行。
- 由于主线不断地重复获取任务、执行任务、再获取任务、再执行任务,这种机制被称为事件循环。
btn.addEventListener('click', function() {
console.log(4)
})
console.log(1)
setTimeout(function() {
console.log(2)
}, 3000)
console.log(3)
以上代码的执行顺序为:1324/1342(取决于点击事件的触发事件)
学习了执行机制后,我们来看一道经典的面试题,代码如下所示:
let timeId = setInterval(function() {
console.log('我是定时器');
}, 3000)
定时器一定是3秒后执行完毕在控制台打印出来吗?
在一开始学习的时候,我们都认为,定时器是在一定时间后执行完毕,因此上面代码会在3秒后打印。
但现在了解了执行机制后,我们知道定时器是异步任务,是等待同步任务全部执行后再去任务队列执行。因此上面的定时器3秒后解析完毕,先送到任务队列内,等同步任务执行完毕再执行。
现如今学习阶段同步任务代码还不是很多,因此解析执行速度很快,等3秒后定时器解析完毕送到任务队列能立即执行;等到后面真正经手业务,代码繁杂后,同步任务执行完毕会需要一定时间,此时定时器不再是3秒后执行了。
location 在开发时的常见应用
location 的数据类型是对象,它拆分并保存了 URL 地址的各个组成部分。常用的属性方法如下:
-
href属性获取完整的URL地址,对其赋值时用于地址的跳转。loacltion.href = 'http://www.baidu.com'因此可用于获取该页面完整的
URL地址,或者页面的链接跳转。 -
search属性获取地址中携带的参数,符号 ? 后面部分。页面跳转中有
GET方式,在链接后面跟英文问号 ? ,问号后面传输数据,多个数据用&&符号隔开,如name=zhangsan&&age=20,因此可以用该方法获取到页面跳转时用户输入的值并应用。 -
hash属性获取地址中的啥希值,符号 # 后面部分。这个应用场景和上面相同,不同之处在于页面跳转时数据传输方式的不同。
-
reload方法用来刷新当前页面,传入参数true时表示强制刷新。这个方法可应用于刷新页面。
json 格式字符串的特性和处理
为什么需要 json 字符串?
因为在做本地存储时只支持存储字符串形式,而到后期庞大的数据量必定会以数组对象的形式出现,直接使用普通方式存储数据虽然系统不会出错,但是存储好的数据会以默认的 toString() 方法转为字符串。
let arr = [1, 2, 3, 4, 5]
let str = {
name: 'dao',
age: 20
}
btn1.addEventListener('click', function() {
localStorage.setItem('dao', arr)
localStorage.setItem('bao', str)
})
btn2.addEventListener('click', function() {
console.log(localStorage.getItem('dao'), typeof localStorage.getItem('dao'));
console.log(localStorage.getItem('bao'), typeof localStorage.getItem('bao'));
})
结果如下图所示。
可以发现,这个结果不是我们想要的,因此我们需要能把复杂数据类型转为字符串形式来做本地存储。 JSON 字符串为此诞生。JSON 字符串能够把复杂数据类型转换为字符串型存储起来,等到需要用到的时候把它转换回原来的数据类型。
JSON 的特点
JSON 主要具有以下特性,这些特性使它成为理想的数据交换语言:
JSON是轻量级的纯文本数据交换格式。JSON具有自我描述性,更易理解,具有层级结构(值中存在值)。JSON采用完全独立于语言的文本格式:JSON使用JavaScript语法来描述数据对象,但是JSON仍然独立于语言和平台。JSON解析器和JSON库支持许多不同的编程语言。 目前常见的动态编程语言(PHP,JSP,.NET)都支持JSON。JSON是存储和交换文本信息的一种语法,它与XML具有相同的特性,是一种数据存储格式,却比XML更小、更快、 更易于人编写和阅读、更易于生成和解析。JSON没有结束标签,更短,读写的速度更快,能够使用内建的JavaScript eval()方法进行解析,使用数组,不使用保留字。
JSON 的处理
json 数据结构(对象和数组)
json 对象:
let obj = {"name":"xiao","age":12};
json 数组:
let objArray = [{"name":"xiao","age":12},{"name":"xiao","age":12}];
处理 json 数据,依赖文件有:jQuery.js
数据格式
JS对象:let obj = {name: "xiao", age: 12};Josn对象:与let obj = {"name":"xiao","age":12};js的对象相比,Josn对象的键值对除了数字以外都需要加双引号。Json字符串let json_str = '{"name":"xiao","age":12}';json的字符串是在原对象基础上最外层加上单引号。
类型转换
Json 字符串 ——>JS 对象,使用方法:
-
将复杂数据转换成
JSON字符串JSON.stringify(复杂数据类型) -
将
JSON字符串转换成对象JSON.parse(JSON字符串)
因此上面的例子可处理为以下形式:
let arr = [1, 2, 3, 4, 5]
let str = {
name: 'dao',
age: 20
}
btn.addEventListener('click', function() {
localStorage.setItem('dao', JSON.stringify(arr))
localStorage.setItem('bao', JSON.stringify(str))
})
document.querySelector('button:nth-of-type(2)').addEventListener('click', function() {
console.log(JSON.parse(localStorage.getItem('dao')));
console.log(JSON.parse(localStorage.getItem('bao')));
})
结果如下图所示。