BOM
BOM(浏览器对象模型)是js真正的核心,BOM提供了很多对象,用于访问浏览器的功能。
1,window对象
- BOM的核心对象是window,它表示浏览器的一个实例。window对象有双重角色,既是通过JS访问浏览器窗口的一个接口,又是ECMAScript规定的Global对象。这意味着在网页中定义的任何一个对象、变量和函数,都以window作为其Global对象。
所有在全局作用域中声明的变量、函数都会变成window对象的属性和方法。
var age = 18
function sayAge () {
console.log(this.age) // 18
}
console.log(window.age) // 18
sayAge()
console.log(window.sayAge()) // 18
我们在全局作用域中定义了变量age和函数sayAge(),他们被自动归在了window对象名下。于是,可以通过window.age访问变量age,通过window.sayAge()访问函数sayAge()
由于sayAge()存在于全局作用域中,因此this.age被映射到window.age。
- JS是单线程语言,它允许通过设置超时值和间歇时间值来调度代码在特定的时刻执行。前者是在指定的时间过后执行,后者是每隔指定的时间就执行一次代码
超时调用需要使用window对象的setTimeout()方法
setTimeout(function, milliseconds, param1, param2, ...)
function: 必需。要调用一个代码串,也可以是一个函数。
milliseconds: 可选。执行或调用 code/function 需要等待的时间,以毫秒计。默认为 0。
param1, param2, ...: 可选。 传给执行函数的其他参数(IE9 及其更早版本不支持该参数)
setTimeout(function () {
console.log('Hello World')
}, 1000)
setTimeout第一个参数不建议传字符串可能会导致性能损失,因此不建议以字符串作为第一个参数
第二个参数:是一个表示等待多长时间的毫秒数,但经过该时间后指定的代码不一定会执行
JS是一个单线程的解析器,因此一定时间内只能执行一段代码,为了控制要执行的代码,就有一个 js任务队列。这些任务会按照将他们添加到队列的顺序执行,setTimeout()的第二个参数告诉JS再过多长时间把当前任务队列添加到队列中,如果队列是空的,那添加的代码会立即执行。如果队列不是空的,那么他就要等前面的代码执行完以后再执行
调用setTimeout()之后,该方法会返回一个数值ID,表示超时调用,这个超时调用ID是计划执行代码的唯一标示符,可以通过它来取消超时调用。取消尚未执行的超时调用,可以调用clearTimeout()方法并对应的超时调用ID作为参数传递给它
let timeoutId = setTimeout(function () {
console.log('Hello world')
}, 1000)
clearTimeout(timeoutId)
以上代码再设置超时调用之后马上又调用了clearTimeout(),结果跟什么也没发生一样。
间歇调用和超时调用类似,只不过它会按照指定的时间间隔重复执行代码,直至间歇调用被取消或者页面被卸载。设置间歇调用的方法是: setInterval(),接受的参数和setTimeout()相同
调用setInterval()方法同样也会返回一个间歇调用ID,该ID可用于在将来某个时刻取消间歇调用,要取消尚未执行的间歇调用,可以使用clearInterval()方法并传入相应的间歇调用ID。
var num = 0
var max = 10
var intervalId = null
function increatNumber () {
num++
// 如果执行次数达到了max设定的值,则取消后续尚未执行的调用
if (num == max) {
clearInterval(intervalId)
console.log('done')
}
}
intervalId = setInterval(increatNumber, 500)
在这个例子中,变量num每半秒钟递增一次,当递增到最大值时会取消先前设定的间歇调用,这个模式也可以使用超时调用实现
var num = 0
var max = 10
function increatNumber () {
num++
if (num < max) {
setTimeout(increatNumber, 500)
} else {
console.log('done')
}
}
setTimeout(increatNumber, 500)
可见,在使用超时调用时,没必要跟踪超时调用ID,因为每次执行完代码后,如果不再设置另一次超时调用,调用就会自行停止。一般认为,使用超时调用来模拟间歇调用是一种最佳模式。在开发环境中,很少使用真正的间歇调用,因为后一个间歇调用可能会在前一个间歇调用结束之后启动。而像前面示例中,则完全可以避免这一点,所以,最好不要使用间歇调用。
location对象
location是最有用的BOM对象之一
image常见面试题:创建一个函数,用以解析查询字符串,然后返回包含所有参数的一个对象
function getQueryStringArgs (url) {
// 取得查询字符串并去掉开头的问号
var qs = url.split('?')[1];
// 保存数据的对象
var args = {},
// 取得第一项
items = qs.length ? qs.split('&') : [],
item = null,
name = null,
value = null,
// 在for循环中使用
i = 0,
len = items.length;
// 逐个将每一项添加到args对象中
for (i = 0; i < len; i++) {
item = items[i].split('=')
name = decodeURIComponent(item[0]) // decodeURIComponent解码name和value,因为查询字符串应该是被编码过的
value = decodeURIComponent(item[1])
if (name.length) {
args[name] = value
}
}
return args
}
let url = 'https://zhidao.baidu.com/question/1768422895052400180.html?fr=iks&word=slice&ie=gbk'
console.log(getQueryStringArgs(url))
history对象
history是window对象的属性,因此每次浏览器窗口、每个标签乃至每个框架都有自己的history对象与特定的window对象关联。
使用go()方法可以在用户的历史记录中任意跳转,可以向后也可以向前。这个方法接受一个参数,表示向后或向前跳转的页面数的一个整数值。负数表示向后跳转(类似于单击浏览器的后退按钮),正数表示向前跳转
history.go(1) // 前进一页
history.go(-1) // 后退一页
也可以给go()传递一个字符串参数,此时浏览器会跳转到历史记录中包含该字符串的第一个位置--可能后退,也可能前进,具体要看哪个位置最近。如果历史记录中不包含该字符串,那么这个方法什么也不做
history.go('wrox.com') // 跳转到最近的wrox.com页面
另外,可以使用back()和forward()来代替go(),顾名思义,这两个方法可以模仿浏览器的后退和前进按钮
history.back() // 后退一页
history.forward() // 前进一页
history对象还有一个length属性,保存着历史记录的数量,这个数量包括所有历史记录,即所有向前和向后的记录。对于加载到窗口、标签页或框架中的第一个页面而言,history.length等于0,通过像下面这样测试该属性的值,可以确定用户是否一开始就打开来你的页面
if (history.length == 0) {
// 这应该是用户打开窗口后的第一个页面
}
小结
浏览器对象模型(BOM)以window对象为依托,表示浏览器窗口以及页面可见区域。同时,window对象还有ECMAScript中的Global对象,因而所有全局变量和函数都是它的属性,且所有原生的构造函数及其他函数也都存在于它的命名空间下。
网友评论