BOM

吐槽君 分类:javascript

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对象之一

BOM
常见面试题:创建一个函数,用以解析查询字符串,然后返回包含所有参数的一个对象

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对象,因而所有全局变量和函数都是它的属性,且所有原生的构造函数及其他函数也都存在于它的命名空间下。

回复

我来回复
  • 暂无回复内容