BOM

BOM 是使用 JavaScript 开发 Web 应用程序的核心。BOM 提供了与网页无关浏览器功能对象。

window 对象

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

window 对象在浏览器中有两重身份,一个是 ECMAScript 中的 Global 对象,另一个就是浏览器窗口的 JavaScript 接口。这意味着网页中定义的所有对象、变量和函数都以 window 作为其 Global 对象,都可以访问其上定义的 parseInt()等全局方法。

因为 window 对象的属性在全局作用域中有效,所以很多浏览器 API 及相关构造函数都以 window 对象属性的形式暴露出来。

Global 作用域

1.通过 var 声明的所有全局变量和函 数都会变成 window对象的属性和方法。

2.如果在这里使用 let 或 const 替代 var,则不会把变量添加给全局对象

3.访问未声明的变量会抛出错误,但是可以在 window 对象上查询是否存在可能未声明的变量。

1
2
3
4
5
// 这会导致抛出错误,因为 oldValue 没有声明
var newValue = oldValue;
// 这不会抛出错误,因为这里是属性查询
// newValue 会被设置为 undefined
var newValue = window.oldValue;

窗口关系

1.top 对象始终指向最上层(最外层)窗口,即浏览器窗口本身

2.parent 对象则始终指向当前窗口的父窗口

3.如果当前窗口是最上层窗口,则 parent 等于 top(都等于 window)

4.最上层的 window 如果不是通过 window.open()打开的,那么其 name 属性就不会包含值

5.self 对象,它是终极 window 属性,始终会指向 window。

窗口位置与像素比

window 对象的位置可以通过不同的属性和方法来确定。

screenLeftscreenTop 属性,用于表示窗口相对于屏幕左侧和顶部的位置 ,返回值的单位是 CSS 像素

**moveTo()**和 **moveBy()**方法移动窗口,这两个方法都接收两个参数,其中

moveTo()接收要移动到的新位置的绝对坐标 x 和 y

moveBy()则接收相对当前位置在两个方向上移动的像素数

1
2
3
4
5
6
7
8
// 把窗口移动到左上角
window.moveTo(0,0);
// 把窗口向下移动 100 像素
window.moveBy(0, 100);
// 把窗口移动到坐标位置(200, 300)
window.moveTo(200, 300);
// 把窗口向左移动 50 像素
window.moveBy(-50, 0);

窗口大小

所有现代浏览器都支持 4 个属性:

innerWidthinnerHeightouterWidthouterHeight

outerWidth 和 outerHeight 返回浏览器窗口自身的大小(不管是在最外层 window 上使用,还是在窗格中使用)。

innerWidth 和 innerHeight 返回浏览器窗口中页面视口的大小(不包含浏览器边框和工具栏)。

document.documentElement.clientWidth 和 document.documentElement.clientHeight 返回页面视口的宽度和高度。

因为桌面浏览器的差异,所以需要先确定用户是不是在使用移动设备,然后再决定使用哪个属性。

用**resizeTo()resizeBy()**方法调整窗口大小。

这两个方法都接收两个参数

resizeTo() 接收新的宽度和高度值

resizeBy()接收宽度和高度各要缩放多少

与移动窗口的方法一样,缩放窗口的*方法可能会被浏览器禁用***,缩放窗口的方法只能应用到最上层的 window 对象。

视口位置

浏览器窗口尺寸通常无法满足完整显示整个页面,为此用户可以通过滚动在有限的视口中查看文档。

度量文档相对于视口滚动距离的属性有两对,返回相等的值:window.pageXoffset/window. scrollXwindow.pageYoffset/window.scrollY

可以使用 scroll()、scrollTo()和 scrollBy()方法滚动页面。这3个方法都接收表示相对视口距 离的 x 和 y 坐标,这两个参数在前两个方法中表示要滚动到的坐标,在最后一个方法中表示滚动的距离。

1
2
3
4
5
6
7
8
// 相对于当前视口向下滚动 100 像素
window.scrollBy(0, 100);
// 相对于当前视口向右滚动 40 像素
window.scrollBy(40, 0);
// 滚动到页面左上角
window.scrollTo(0, 0);
// 滚动到距离屏幕左边及顶边各 100 像素的位置
window.scrollTo(100, 100);

除了提供偏移值,还可以通过 behavior 属性告诉浏览器是否平滑滚动

1
2
3
4
5
6
7
8
9
10
11
12
13

// 正常滚动
window.scrollTo({
left: 100,
top: 100,
behavior: 'auto'
});
// 平滑滚动
window.scrollTo({
left: 100,
top: 100,
behavior: 'smooth'
});

导航与打开新窗口

window.open()方法可以用于导航到指定 URL

这个方法接收 4 个参数:

要加载的 URL目标窗口特性字符串表示新窗口在浏览器历史记录中是否替代当前加载页面的布尔值

如果 window.open()的第二个参数是一个已经存在的窗口或窗格(frame)的名字,则会在对应的窗口或窗格中打开URL。

1
2
// 与<a href="http://www.wrox.com" target="topFrame"/>相同
window.open("http://www.wrox.com/", "topFrame");

执行这行代码的结果就如同用户点击了一个 href 属性为”http://www.wrox.com",target 属 性为”topFrame”的链接。如果有一个窗口名叫”topFrame”,则这个窗口就会打开这个 URL;否则就会打开一个新窗口并将其命名为”topFrame”。

第二个参数也可以是一个特殊的窗口名,比如**_self、 _parent、_top 或_blank。**

弹出窗口

如果 window.open()的第二个参数不是已有窗口,则会打开一个新窗口或标签页。第三个参数, 即特性字符串,用于指定新窗口的配置。如果没有传第三个参数,则新窗口(或标签页)会带有所有默认的浏览器特性(工具栏、地址栏、状态栏等都是默认配置)。如果打开的不是新窗口,则忽略第三个参数。

特性字符串是一个逗号分隔的设置字符串,用于指定新窗口包含的特性

这些设置需要以逗号分隔的名值对形式出现,其中名值对以等号连接。

特性字符串中不能包含空格

window.open()方法返回一个对新建窗口的引用

可以使用这个对象操纵新打开的窗口。

1
2
3
4
let wroxWin=window.open("http://www.wrox.com/", 
"wroxWindow",
"height=400,width=400,top=10,left=10,resizable=yes");
//这行代码会打开一个可缩放的新窗口,大小为 400 像素×400 像素,位于离屏幕左边及顶边各 10 像素的位置。

可以使用 close()方法像这样关闭新打开的窗口:

1
2
wroxWin.close(); 
alert(wroxWin.closed); // true

新创建窗口的 window 对象有一个属性 opener,指向打开它的窗口。这个属性只在弹出窗口的最上层 window 对象(top)有定义,是指向调用 window.open()打开它的窗口或窗格的指针。

1
2
3
4
5
let wroxWin = window.open("http://www.wrox.com/", 
"wroxWindow",
"height=400,width=400,top=10,left=10,resizable=yes");
alert(wroxWin.opener === window); // true

可以将新打开的标签页的 opener 属性设置为 null,表示新打开的标签页可以运行在独立的进程中。

1
2
3
4
let wroxWin = window.open("http://www.wrox.com/", 
"wroxWindow",
"height=400,width=400,top=10,left=10,resizable=yes");
wroxWin.opener = null;

把 opener 设置为 null 表示新打开的标签页不需要与打开它的标签页通信,因此可以在独立进程 中运行。这个连接一旦切断,就无法恢复了。

弹窗屏蔽程序

所有现代浏览器都内置了屏蔽弹窗的程序,因此大多数意料之外的弹窗都会被屏蔽。在浏览器屏蔽弹窗时,可能会发生一些事。如果浏览器内置的弹窗屏蔽程序阻止了弹窗,那么 window.open()很可能会返回null。此时,只要检查这个方法的返回值就可以知道弹窗是否被屏蔽了

1
2
3
4
let wroxWin = window.open("http://www.wrox.com", "_blank"); 
if (wroxWin == null){
alert("The popup was blocked!");
}

window.open()通常会抛出错误。

因此要准确检测弹窗是否被屏蔽,除了检测 window.open()的返回值,还要把它用 try/catch 包装起来

1
2
3
4
5
6
7
8
9
10
11
12
let blocked = false;
try {
let wroxWin = window.open("http://www.wrox.com", "_blank");
if (wroxWin == null){
blocked = true;
}
} catch (ex){
blocked = true;
}
if (blocked){
alert("The popup was blocked!");
}

定时器

**setTimeout()**用于指定在一定时间后执行某些代码

setInterval()用于指定每隔一段时间执行某些代码。

setTimeout()方法通常接收两个参数:要执行的代码和在执行回调函数前等待的时间(毫秒)。

第一个参数可以是包含 JavaScript 代码的字符串或者一个函数。

第二个参数是要等待的毫秒数,而不是要执行代码的确切时间。

调用 setTimeout()时,会返回一个表示该超时排期的数值 ID。这个超时 ID 是被排期执行代码的唯一标识符,可用于取消该任务。

只要是在指定时间到达之前调用 clearTimeout(),就可以取消超时任务。在任务执行后再调用 clearTimeout()没有效果

系统对话框

alert()、confirm()和 prompt()方法,可以让浏览器调用系统对话框向用户显示消息。这 些对话框与浏览器中显示的网页无关,而且也不包含 HTML。它们的外观由操作系统或者浏览器决定, 无法使用 CSS 设置。

这些对话框都是同步的模态对话框,即在它们显示的时候,代码会停止执行, 在它们消失以后,代码才会恢复执行。

alert()警告框只接收一个参数。调用 alert()时,传入 的字符串会显示在一个系统对话框中。对话框只有一个“OK”(确定)按钮。如果传给 alert()的参数不是一个原始字符串,则会调用这个值的 toString()方法将其转换为字符串。

confirm()确认框跟警告框类似,都会向用户显示消息。但不同之处在于,确认框有两个按钮:“Cancel”(取消)和“OK”(确定)。用户通过单击不同的按 钮表明希望接下来执行什么操作,要知道用户单击了 OK 按钮还是 Cancel 按钮,可以判断 confirm()方法的返回值:true 表示单击 了 OK 按钮,false 表示单击了 Cancel 按钮或者通过单击某一角上的 X 图标关闭了确认框。

prompt()提示框

提示框的用途是提示用户输入消息。 除了 OK 和 Cancel 按钮,提示框还会显示一个文本框,让用户输入内容。prompt()方法接收两个参数: 要显示给用户的文本,以及文本框的默认值(可以是空字符串)

1
prompt("What is your name?",  "Jake")

如果用户单击了 OK 按钮,则 prompt()会返回文本框中的值

如果用户单击了 Cancel 按钮,或者对话框被关闭,则 prompt()会返回 null

JavaScript 还可以显示另外两种对话框:find()和 print()。

用户在浏览器菜单上选择“查找”(find)和“打印”(print)时显示的就是这 两种对话框。

1
2
3
4
// 显示打印对话框
window.print();
// 显示查找对话框
window.find();

location 对象

location提供了当前窗口中加载文档的信息,以及通常的导航功能

这个对象独特的地方在于,它既是 window 的属性,也是 document 的属性

location 对象不仅保存着当前加载文档的信息,也保存着把 URL 解析为离散片段后能够通过属性访问的信息

假设浏览器当前加载的 URL 是 http://foouser:barpassword@www.wrox.com:80/WileyCDA/?q=javascript#contents,location 对象的内容如下表

查询字符串

虽然 location.search 返回了从问号开始直到 URL 末尾的所有内容,但没有办法逐个访问每个查询参数。

操作地址

可以通过修改 location 对象修改浏览器的地址。设置 location.href 是最常见的。

首先,使用 assign()方法并传入一 个URL,如下所示:

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

这行代码会立即启动导航到新 URL 的操作,同时在浏览器历史记录中增加一条记录。

如果给 location.href 或 window.location 设置一个 URL,也会以同一个 URL 值调用 assign()方法。

比如,下面两行代码都会执行与显式调用 assign()一样的操作:

1
2
3
window.location = "http://www.wrox.com"; 

location.href = "http://www.wrox.com";

在以前面提到的方式修改 URL 之后,浏览器历史记录中就会增加相应的记录。当用户单击“后退” 按钮时,就会导航到前一个页面。如果不希望增加历史记录,可以使用 replace()方法。这个方法接收一个URL 参数,但重新加载后不会增加历史记录。调用 replace()之后,用户不能回到前一页。

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html> 
<html>
<head>
<title>You won't be able to get back here</title>
</head>
<body>
<p>Enjoy this page for a second, because you won't be coming back here.</p>
<script>
setTimeout(() => location.replace("http://www.wrox.com/"), 1000);
</script>
</body>
</html>

浏览器加载这个页面 1 秒之后会重定向到 www.wrox.com。此时,“后退”按钮是禁用状态,即不能返回这个示例页面,除非手动输入完整的 URL。

最后一个修改地址的方法是 reload(),它能重新加载当前显示的页面。调用 reload()而不传参数,页面会以最有效的方式重新加载。

也就是说,如果页面自上次请求以来没有修改过,浏览器可能会 从缓存中加载页面。

如果想强制从服务器重新加载,可以像下面这样给 reload()传个 true:

1
2
location.reload(); // 重新加载,可能是从缓存加载
location.reload(true); // 重新加载,从服务器加载

脚本中位于 reload()调用之后的代码可能执行也可能不执行,这取决于网络延迟和系统资源等因 素。为此,最好把 reload()作为最后一行代码。

navigator 现在已经成为客户端标识浏览器的标准

navigator 对象的属性通常用于确定浏览器的类型

检测插件

检测浏览器是否安装了某个插件可以通过 plugins 数组来确定

 name:插件名称。

 description:插件介绍。

 filename:插件的文件名。

 length:由当前插件处理的 MIME 类型数量

name 属性包含识别插件所需的必要信息

检测插件就是遍历浏览器中可用的插件,并逐个比较插件的名称

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 插件检测,IE10 及更低版本无效 
let hasPlugin = function(name) {
name = name.toLowerCase();
for (let plugin of window.navigator.plugins){
if (plugin.name.toLowerCase().indexOf(name) > -1){
return true;
}
}
return false;
}
// 检测 Flash
alert(hasPlugin("Flash"));
// 检测 QuickTime
alert(hasPlugin("QuickTime"));

注册处理程序

现代浏览器支持 navigator 上的registerProtocolHandler()方法。

这个方法可以把一个网站注册为处理某种特定类型信息应用程序。随着在线 RSS 阅读器和电子邮件客户端的流行,可以借助这个方法将 Web 应用程序注册为像桌面软件一样的默认应用程序。

screen 对象

window 的另一个属性 screen 对象,是为数不多的几个在编程中很少用的 JavaScript 对象。这个对象中保存的纯粹是客户端能力信息,也就是浏览器窗口外面的客户端显示器的信息,比如像素宽度和像素高度。每个浏览器都会在 screen 对象上暴露不同的属性。

history 对象

history 对象表示当前窗口首次使用以来用户的导航历史记录。因为 history 是 window 的属性, 所以每个 window 都有自己的 history 对象

出于安全考虑,这个对象不会暴露用户访问过的 URL, 但可以通过它在不知道实际 URL 的情况下前进和后退。

导航

go()方法可以在用户历史记录中沿任何方向导航,可以前进也可以后退。这个方法只接收一个参数, 这个参数可以是一个整数表示前进或后退多少步负值表示在历史记录中后退(类似点击浏览器的“后退”按钮),而正值表示在历史记录中前进(类似点击浏览器的“前进”按钮)。

1
2
3
4
5
6
7
// 后退一页
history.go(-1);
// 前进一页
history.go(1);
// 前进两页
history.go(2);

go()有两个简写方法:**back()和 forward()**。

顾名思义,这两个方法模拟了浏览器的后退按钮和前进按钮

1
2
3
// 后退一页 history.back();  

// 前进一页 history.forward();

history 对象还有一个 length 属性,表示历史记录中有多个条目。这个属性反映了历史记录的数量,包括可以前进和后退的页面。

1
2
3
if (history.length == 1){ 
// 这是用户窗口中的第一个页面
}

history 对象通常被用于创建“后退”和“前进”按钮,以及确定页面是不是用户历史记录中的第
一条记录

历史状态管理