目录

第八章 - BOM

本章内容

  • 理解 window 对象——BOM 的核心
  • 控制窗口、框架和弹出窗口
  • 利用 location 对象中的页面信息
  • 使用 navigator 对象了解浏览器

BOM(浏览器对象模型) 提供了很多对象,用于访问浏览器的功能,这些功能与任何网页内容无关。

8.1 window 对象

BOM 的核心对象是 window,它表示浏览器的一个实例。

8.1.1 全局作用域

由于 window 对象同时扮演着 ECMAScript 中 Global 对象的角色,因此所有在全局作用域中声明的变量、函数都会变成 window 对象的属性和方法。 定义全局变量与在 window 对象上直接定义属性还是有一点差别:全局变量不能通过 delete 操作符删除,而直接在 window 对象上的定义的属性可以。

8.1.2 窗口关系及框架

如果页面中包含框架,则每个框架都拥有自己的 window 对象,并且保存在 frames集合中。

<html> 
    <head> 
        <title>Frameset Example</title> 
    </head> 
    <frameset rows="160,*"> 
        <frame src="frame.htm" name="topFrame"> 
        <frameset cols="50%,50%"> 
            <frame src="anotherframe.htm" name="leftFrame"> 
            <frame src="yetanotherframe.htm" name="rightFrame"> 
        </frameset> 
    </frameset> 
</html> 

https://raw.githubusercontent.com/codingbylch/Figure_bed_for_blog/master/img_for_blog/20200323124653.png

与框架有关的最后一个对象是 self,它始终指向 window;实际上,self 和 window 对象可以互换使用。引入 self 对象的目的只是为了与 top 和 parent 对象对应起来,因此它不格外包含其他值。

8.1.3 窗口位置

IE、Safari、Opera 和 Chrome 都提供了screenLeft 和 screenTop 属性,分别用于表示窗口相对于屏幕左边和上边的位置。 moveTo()和 moveBy()方法都接收两个参数,moveTo()接收的是新位置的 x 和 y 坐标值,而 moveBy()接收的是在水平和垂直方向上移动的像素数:

//将窗口移动到屏幕左上角 
window.moveTo(0,0); 
 
//将窗向下移动 100 像素 
window.moveBy(0,100); 
 
//将窗口移动到(200,300) 
window.moveTo(200,300); 
 
//将窗口向左移动 50 像素 
window.moveBy(-50,0);

另外,这两个方法都不适用于框架,只能对最外层的 window 对象使用。

8.1.4 窗口大小

innerWidth、innerHeight、outerWidth 和 outerHeight。在 Chrome 中,outerWidth、outerHeight 与innerWidth、innerHeight 返回相同的值,即视口(viewport)大小而非浏览器窗口大小。 虽然最终无法确定浏览器窗口本身的大小,但却可以取得页面视口的大小,如下所示。

var pageWidth = window.innerWidth, 
    pageHeight = window.innerHeight; 
     
if (typeof pageWidth != "number"){ 
    if (document.compatMode == "CSS1Compat"){ 
        pageWidth = document.documentElement.clientWidth; 
        pageHeight = document.documentElement.clientHeight; 
    } else { 
        pageWidth = document.body.clientWidth; 
        pageHeight = document.body.clientHeight; 
    } 
} 

略。

8.1.5 导航和打开窗口

使用 **window.open()**方法既可以导航到一个特定的 URL,也可以打开一个新的浏览器窗口。这个方法可以接收 4 个参数:要加载的 URL、窗口目标、一个特性字符串以及一个表示新页面是否取代浏览器历史记录中当前加载页面的布尔值。通常只须传递第一个参数,最后一个参数只在不打开新窗口的情况下使用。 如果为 window.open()传递了第二个参数,而且该参数是已有窗口或框架的名称,那么就会在具有该名称的窗口或框架中加载第一个参数指定的 URL。

  • 弹出窗口 如果给 window.open()传递的第二个参数并不是一个已经存在的窗口或框架,那么该方法就会根据在第三个参数位置上传入的字符串创建一个新窗口或新标签页。如果没有传入第三个参数,那么就会打开一个带有全部默认设置(工具栏、地址栏和状态栏等)的新浏览器窗口(或者打开一个新标签页——根据浏览器设置)。在不打开新窗口的情况下,会忽略第三个参数。 第三个参数是一个逗号分隔的设置字符串,表示在新窗口中都显示哪些特性。下表展示了这个字符串的设置选项: https://raw.githubusercontent.com/codingbylch/Figure_bed_for_blog/master/img_for_blog/20200323131709.png
window.open("http://www.wrox.com/","wroxWindow", 
            "height=400,width=400,top=10,left=10,resizable=yes");
//调整大小 
wroxWin.resizeTo(500,500); 
 
//移动位置 
wroxWin.moveTo(100,100);
// 调用 close()方法还可以关闭新打开的窗口。 
wroxWin.close(); 

这行代码会打开一个新的可以调整大小的窗口,窗口初始大小为 400×400 像素,并且距屏幕上沿和左边各 10 像素,然后调整大小、移动位置,关闭窗口。弹出窗口可以调用 top.close()在不经用户允许的情况下关闭自己。 新创建的 window 对象有一个 opener 属性,其中保存着打开它的原始窗口对象,但原始窗口中并没有这样的指针指向弹出窗口,只能在必要的时候自己来手动实现跟踪。

  • 安全限制 略

  • 弹出窗口屏蔽程序 略

8.1.6 间歇调用和超时调用

超时调用:需要使用 window 对象的 setTimeout()方法,它接受两个参数:要执行的代码和以毫秒表示的时间(即在执行代码前需要等待多少毫秒)。其中,第一个参数可以是一个包含 JavaScript 代码的字符串(就和在 eval()函数中使用的字符串一样),也可以是一个函数。推荐第二种。 第二个参数是一个表示等待多长时间的毫秒数,但经过该时间后指定的代码不一定会执行。setTimeout()的第二个参数告诉 JavaScript 再过多长时间把当前任务添加到队列中。如果队列是空的,那么添加的代码会立即执行;如果队列不是空的,那么它就要等前面的代码执行完了以后再执行。 可以调用clearTimeout()方法并将相应的超时调用 ID 作为参数传递给它,来取消超时调用。

间歇调用setInterval():会按照指定的时间间隔重复执行代码,直至间歇调用被取消或者页面被卸载。 要取消尚未执行的间歇调用,可以使用 clearInterval()方法并传入相应的间歇调用 ID,否则间歇调用会一直执行。以下是一个常见的使用间歇调用的例子:

var num = 0; 
var max = 10; 
var intervalId = null; 
 
function incrementNumber() { 
    num++; 
 
 //如果执行次数达到了 max 设定的值,则取消后续尚未执行的调用 
    if (num == max) { 
        clearInterval(intervalId); 
        alert("Done"); 
    } 
} 
 
intervalId = setInterval(incrementNumber, 500); 

在开发环境下,很少使用真正的间歇调用,原因是后一个间歇调用可能会在前一个间歇调用结束之前启动。

8.1.7 系统对话框

浏览器通过 alert()、confirm()和 prompt()方法可以调用系统对话框向用户显示消息。 具体介绍略。

8.2 location 对象

location 是最有用的 BOM 对象之一,它提供了与当前窗口中加载的文档有关的信息,还提供了一些导航功能。window.location 和 document.location 引用的是同一个对象。下表列出了 location 对象的所有属性: https://raw.githubusercontent.com/codingbylch/Figure_bed_for_blog/master/img_for_blog/20200323154259.png

8.2.1 查询字符串参数

location.search 返回从问号到 URL 末尾的所有内容,但却没有办法逐个访问其中的每个查询字符串参数。为此,可以像下面这样创建一个函数,用以解析查询字符串:

function getQueryStringArgs(){ 
    //取得查询字符串并去掉开头的问号 
    var qs = (location.search.length > 0 ? location.search.substring(1) : ""), 
     
    //保存数据的对象 
    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]); 
        value = decodeURIComponent(item[1]); 
 
        if (name.length) { 
            args[name] = value; 
        } 
    } 
     
    return args; 
} 

8.2.2 位置操作

使用 location 对象可以通过很多方式来改变浏览器的位置。

location.assign("https://www.baidu.com"); // 跳转到百度
// 等价于
window.location = "http://www.wrox.com"; 
location.href = "http://www.wrox.com";

另外,修改 location对象的其他属性也可以改变当前加载的页面。

//假设初始 URL 为 http://www.wrox.com/WileyCDA/ 
 
//将 URL 修改为"http://www.wrox.com/WileyCDA/#section1" 
location.hash = "#section1"; 
 
//将 URL 修改为"http://www.wrox.com/WileyCDA/?q=javascript" 
location.search = "?q=javascript"; 
 
//将 URL 修改为"http://www.yahoo.com/WileyCDA/" 
location.hostname = "www.yahoo.com"; 
 
//将 URL 修改为"http://www.yahoo.com/mydir/" 
location.pathname = "mydir"; 
 
//将 URL 修改为"http://www.yahoo.com:8080/WileyCDA/" 
location.port = 8080; 

每次修改 location 的属性(hash 除外),页面都会以新 URL 重新加载。 调用 replace()方法之后,用户不能回到前一个页面:

location.replace("http://www.wrox.com/"); 

与位置有关的最后一个方法是 reload(),作用是重新加载当前显示的页面。

location.reload();        //重新加载(有可能从缓存中加载) 
location.reload(true);    //重新加载(从服务器重新加载)

8.3 navigator 对象

navigator 对象的属性通常用于检测显示网页的浏览器类型。

8.3.1 检测插件

检测浏览器中是否安装了特定的插件是一种最常见的检测例程。对于非 IE 浏览器,可以使用plugins 数组来达到这个目的。

//检测插件(在 IE 中无效) 
function hasPlugin(name){ 
    name = name.toLowerCase(); 
    for (var i=0; i < navigator.plugins.length; i++){ 
        if (navigator. plugins [i].name.toLowerCase().indexOf(name) > -1){ 
            return true; 
        } 
    } 
 
    return false; 
} 
 
//检测 Flash 
alert(hasPlugin("Flash")); 
 
//检测 QuickTime 
alert(hasPlugin("QuickTime"));

8.3.2 注册处理程序

registerContentHandler()和 registerProtocolHandler()方法可以让一个站点指明它可以处理特定类型的信息。随着 RSS 阅读器和在线电子邮件程序的兴起,注册处理程序就为像使用桌面应用程序一样默认使用这些在线应用程序提供了一种方式。 略。

8.4 screen 对象

screen 对象基本上只用来表明客户端的能力,其中包括浏览器窗口外部的显示器的信息,如像素宽度和高度等。 https://raw.githubusercontent.com/codingbylch/Figure_bed_for_blog/master/img_for_blog/20200323194308.png https://raw.githubusercontent.com/codingbylch/Figure_bed_for_blog/master/img_for_blog/20200323194357.png 这些信息经常集中出现在测定客户端能力的站点跟踪工具中,但通常不会用于影响功能。不过,有时候也可能会用到其中的信息来调整浏览器窗口大小,使其占据屏幕的可用空间。

8.5 history 对象

history 对象保存着用户上网的历史记录,从窗口被打开的那一刻算起。每个浏览器窗口、每个标签页乃至每个框架,都有自己的 history 对象与特定的window 对象关联。 使用 go()方法可以在用户的历史记录中任意跳转。

//后退一页 
history.go(-1); 
 
//前进一页 
history.go(1); 
 
//前进两页 
history.go(2);

也可以给 go()方法传递一个字符串参数,此时浏览器会跳转到历史记录中包含该字符串的第一个位置。 history 对象还有一个 length 属性,保存着历史记录的数量。

8.6 小结

本章讨论了下列 BOM 的组成部分。

  • 在使用框架时,每个框架都有自己的 window 对象以及所有原生构造函数及其他函数的副本。 每个框架都保存在 frames 集合中,可以通过位置或通过名称来访问。
  • 有一些窗口指针,可以用来引用其他框架,包括父框架。
  • top 对象始终指向最外围的框架,也就是整个浏览器窗口。
  • parent 对象表示包含当前框架的框架,而 self 对象则回指 window。
  • 使用 location 对象可以通过编程方式来访问浏览器的导航系统。设置相应的属性,可以逐段或整体性地修改浏览器的 URL。
  • 调用 replace()方法可以导航到一个新 URL,同时该 URL 会替换浏览器历史记录中当前显示的页面。
  • navigator 对象提供了与浏览器有关的信息。

BOM 中还有两个对象:screen 和 history。screen 对象中保存着与客户端显示器有关的信息,这些信息一般只用于站点分析。history 对象为访问浏览器的历史记录开了一个小缝隙,开发人员可以据此判断历史记录的数量,也可以在历史记录中向后或向前导航到任意页面。