技术思考 【操作浏览器】

137 阅读8分钟

操作浏览器

BOM 是浏览器对象模型,包括 window (最高级的对象)、 loactionnavigationdocument (即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)

结果打印台没输出任何内容。

无效果.png 但是为了代码的理解性与健康性,建议对应使用方法来清除。

拓展:如何让延时器与定时器产生对方的效果。

根据上面所述,延时器只执行一次,定时器每隔一段时间就执行一次,如何让他们实现对方的效果,让定时器只执行一次,让延时器每隔一段时间就执行一次呢?

  • 通过递归,让 setTimeout 内部嵌套自身,执行完一次再执行,执行完后再执行······可以实现 setInterval 的效果。

    function test() {
        console.log('我是延时器');
        setTimeout(test, 5000)
    }
    test()
    

    注意:

    这里延时器内的函数 test 后面不能跟括号,否则报错。

    加括号报错.png 因为这里的函数不是由我们程序员自己调用的,而是要延时器调用的,因此是回调函数,如果加了括号就变成立即执行函数,会自主调用到超出范围报错。

  • 通过自清除,让 setInterval 内部设置清除定时器的语句,让其执行第一次之后就被清除,可实现 setTimeout的效果。

    let timeId = setInterval(function() {
        console.log('我是定时器');
        clearInterval(timeId)
    }, 3000)
    

互换.png

js 的执行机制

聊完定时器与延时器,接下来说说 js 的执行机制。

由于用户在操作浏览器页面的元素节点数据时只能单线程操作(即用户想要实现编辑与增加功能必须先编辑再添加或先添加再编辑,不能同一时间一边实现数据编辑一边实现数据添加),因此从一开始就决定了 javascript 是一个自上而下逐一执行的单线程代码。

但是根据我们的生活经验我们知道,如果一件事情没做完就等待那件事情做完再做下一件事情,效率十分低下,为了解决这个问题, javascript 提出了同步与异步的概念。

同步

同步即前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。

打个比方,妈妈出门前为你列了个清单,让你煮饭、做菜、洗衣服,同步执行的顺序是你先把生米放进电饭煲内煮饭,然后就坐在旁边干等,等他煮熟了再去做菜洗衣服。

但是这样极不合理。异步的概念就出来了。

异步

异步即在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。

还是同一个例子,妈妈让你煮饭、做菜、洗衣服,异步是检索这几个步骤,发现煮饭很花费时间,因此你把米洗好放进电饭煲按下开关让它煮饭,自己就可抽身去处理别的事情了。

javascript 中,异步任务又分为以下三种:

  • 普通事件,如 click 、resize 等
  • 资源加载,如 load 、error 等
  • 定时器,包括 setInterval 、setTimeout 等

执行机制

  1. 先执行执行栈中的同步任务,异步任务(回调函数)放入任务队列中(任务队列也称为消息队列),由浏览器代替解析,解析完毕后按顺序放进任务队列内。
  2. 执行栈中所有同步任务执行完毕,系统会按次序读取任务队列中已执行完毕的异步任务,开始执行。
  3. 由于主线不断地重复获取任务、执行任务、再获取任务、再执行任务,这种机制被称为事件循环。
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'));
})

结果如下图所示。

获取本地存储.png

可以发现,这个结果不是我们想要的,因此我们需要能把复杂数据类型转为字符串形式来做本地存储。 JSON 字符串为此诞生。JSON 字符串能够把复杂数据类型转换为字符串型存储起来,等到需要用到的时候把它转换回原来的数据类型。

JSON 的特点

JSON 主要具有以下特性,这些特性使它成为理想的数据交换语言:

  • JSON 是轻量级的纯文本数据交换格式。
  • JSON 具有自我描述性,更易理解,具有层级结构(值中存在值)。
  • JSON 采用完全独立于语言的文本格式:JSON 使用 JavaScript 语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。 目前常见的动态编程语言(PHPJSP.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 对象,使用方法:

  1. 将复杂数据转换成 JSON 字符串

    JSON.stringify(复杂数据类型)
    
  2. 将 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')));
})

结果如下图所示。

json.png