Ch 12 BOM
BOM: Browser Object Model,浏览器模型对象
12.1 window 对象
BOM的核心是window对象,表示浏览器的实例。
12.1.1 Global 作用域
window对象被复用为 ECMAScript 的 Global 对象,通过var声明的所有全局变量和函数都会变成window对象的属性和方法。如果是通过let 和 const 声明的变量或方法,则不会把变量添加给全局变量window。
var age = 29;
var printAge = ()=> alert(this.age);
alert(window.age); // 29
printAge(); // 29
window.printAge() // 29
// 用let声明
let age = 29;
const printAge = ()=> alert(this.age);
alert(window.age); // undefined
printAge(); // undefined
window.printAge() // TypeError: window.printAge is not a function
JavaScript 中有很多对象都暴露在全局作用域中,比如 location 和 navigator,因而它们也是 window 对象的属性。
12.1.2 窗口关系
- window.top:top 对象始终指向最上层(最外层)窗口,即浏览器窗口本身。
- window.parent:parent 对象则始终指向当前窗口的父窗口。
- window.self:始终会指向 window。实际上,self 和 window 就是同一个对象。
12.1.3 窗口位置
window 对象的位置可以通过不同的属性和方法来确定。现代浏览器提供了 screenLeft 和 screenTop 属性,用于表示窗口相对于屏幕左侧和顶部的位置 ,返回值的单位是 CSS 像素。
可以使用 moveTo()和 moveBy()方法移动窗口。这两个方法都接收两个参数,其中 moveTo()接 收要移动到的新位置的绝对坐标 x 和 y;而 moveBy()则接收相对当前位置在两个方向上移动的像素数。但是,以上方法可能会被部分或全部禁用,这取决于浏览器。
12.1.4 窗口大小
所有现代浏览器都支持 4 个属性: innerWidth、innerHeight、outerWidth 和 outerHeight。
outerWidth 和 outerHeight 返回浏 览器窗口自身的大小(不管是在最外层 window 上使用,还是在窗格中使用)。
innerWidth 和 innerHeight 返回浏览器窗口中页面视口的大小(不包含浏览器边框和工具栏)。
12.1.5 视口位置
度量文档相对于视口滚动距离的属性有两对,返回相等的值:
- window.pageXoffset/window.scrollX
- window.pageYoffset/window.scrollY。
使用 scroll()、scrollTo()和 scrollBy()方法滚动页面。这 3 个方法都接收表示相对视口距离的 x 和 y 坐标,这两个参数在前两个方法中表示要滚动到的坐标,在最后一个方法中表示滚动的距离。
12.1.6 导航与打开新窗口
window.open()方法可以用于导航到指定 URL,也可以用于打开新浏览器窗口。这个方法接收 4 个参数:
- 要加载的 URL
- 目标窗口
- 特性字符串
- 表示新窗口在浏览器历史记录中是否替代当前加载页面的布尔值。
window.open("http://www.google.com/",
"googleWindow",
"height=400,width=400,top=10,left=10,resizable=yes");
12.1.7 定时器
JavaScript 在浏览器中是单线程执行的,但允许使用定时器指定在某个时间之后或每隔一段时间就执行相应的代码。setTimeout()用于指定在一定时间后执行某些代码,而 setInterval()用于指定每隔一段时间执行某些代码。
setTimeout()方法通常接收两个参数:要执行的代码和在执行回调函数前等待的时间(毫秒)。
为了调度不同代码的执行,JavaScript 维护了一个任务队列。其中的任务会按照添加到队列的先后顺序执行。setTimeout()的第二个参数只是告诉 JavaScript 引擎在指定的毫秒数过后把任务添加到这个队列。如果队列是空的,则会立即执行该代码。如果队列不是空的,则代码必须等待前面的任务执行完才能执行。
调用 setTimeout()时,会返回一个表示该超时排期的数值 ID。这个超时 ID 是被排期执行代码的 唯一标识符,可用于取消该任务。要取消等待中的排期任务,可以调用 clearTimeout()方法并传入超 时 ID,
// 设置超时任务
let timeoutId = setTimeout(() => alert("Hello world!"), 1000);
// 取消超时任务
clearTimeout(timeoutId);
12.1.8 对话框
浏览器自带三种对话框
- alert
alert("Hello World")
- confirm
if (confirm("Are you sure?")) {
alert("I'm so glad you're sure!");
} else {
alert("I'm sorry to hear you're not sure.");
}
- prompt
let result = prompt("What is your name? ", "");
if (result !== null) {
alert("Welcome, " + result);
}
12.2 location 对象
location 是最有用的 BOM 对象之一,提供了当前窗口中加载文档的信息,以及通常的导航功能。它既是 window 的属性,也是 document 的属性。也就是说, window.location 和 document.location 指向同一个对象。
假设浏览器当前加载的 URL 是 foouser:barpassword@www.wrox.com:80/WileyCDA/?q…,location 对象的内容如下图所示。
12.2.1 查询字符串
URLSearchParams 提供了一组标准 API 方法,通过它们可以检查和修改查询字符串。给 URLSearchParams 构造函数传入一个查询字符串,就可以创建一个实例。这个实例上暴露了 get()、 set()和 delete()等方法,可以对查询字符串执行相应操作。
let qs = "?q=javascript&num=10";
let searchParams = new URLSearchParams(qs);
alert(searchParams.toString()); // " q=javascript&num=10"
searchParams.has("num"); // true
searchParams.get("num"); // 10
searchParams.set("page", "3");
alert(searchParams.toString()); // " q=javascript&num=10&page=3"
searchParams.delete("q");
alert(searchParams.toString()); // " num=10&page=3"
12.2.2 操作地址
可以通过修改 location 对象修改浏览器的地址。
首先,最常见的是使用 assign()方法并传入一 个 URL。assign会立即启动导航到新 URL 的操作,同时在浏览器历史记录中增加一条记录。如果给 location.href 或 window.location 设置一个 URL,也会以同一个 URL 值调用 assign()方法。
location.assign("http://www.wrox.com")
window.location = "http://www.wrox.com";
location.href = "http://www.wrox.com";
// 这三行代码是等价的
如果不希望增加历史记录,可以使用 replace()方法。这个方法接收一个 URL 参数,但重新加载后不会增加历史记录。调用 replace()之后,用户不能回到前一页。
reload()方法能重新加载当前显示的页面。调用 reload()而不传参数,页面会以最有效的方式重新加载。也就是说,如果页面自上次请求以来没有修改过,浏览器可能会从缓存中加载页面。如果想强制从服务器重新加载,可以给 reload()传个 true。
location.reload(); // 重新加载,可能是从缓存加载
location.reload(true); // 重新加载,从服务器加载
12.3 navigator 对象
12.3.1 检测插件
检测浏览器是否安装了某个插件是开发中常见的需求。
function hasPlugin(name) {
name = name.toLowerCase();
for(let plugin of window.navigator.plugins) {
if (plugin.name.toLowerCase().indexOf(name) > -1) {
return true;
}
}
return false;
}
12.3.2 注册处理程序
现代浏览器支持 navigator 上的(在 HTML5 中定义的)registerProtocolHandler()方法。 这个方法可以把一个网站注册为处理某种特定类型信息应用程序。
12.4 screen 对象
window 的另一个属性 screen 对象。这个对象中保存的纯粹是客户端能力信息,也就是浏览器窗口外面的客户端显示器的信息,比如像素宽度和像素高度。每个浏览器都会在 screen 对象上暴露不同的属性。
12.5 history 对象
12.5.1 导航
go()方法可以在用户历史记录中沿任何方向导航,可以前进也可以后退。这个方法只接收一个参数, 这个参数可以是一个整数,表示前进或后退多少步。
// 后退一页
history.go(-1); // 等价于 history.back()
// 前进一页
history.go(1); // 等价于 history.forward()
// 前进两页
history.go(2);
history 对象通常被用于创建“后退”和“前进”按钮,以及确定页面是不是用户历史记录中的第一条记录。
12.5.2 历史状态管理
HTML5 为 history 对象增加了方便的状态管理特性。状态管理 API 则可以让开发者改变浏览器 URL 而不会加载新页面。
history.pushState()方法。这个方法接收 3 个参数:一个 state 对象、一个新状态的标题和一个(可选的)相对 URL。
let stateObject = {foo:"bar"};
history.pushState(stateObject, "My title", "baz.html");
pushState()方法执行后,状态信息就会被推到历史记录中,浏览器地址栏也会改变以反映新的相对URL。
使用 HTML5 状态管理时,要确保通过 pushState()创建的每个“假”URL 背后都对应着服务器上一个真实的物理 URL。否则,单击“刷新”按钮会导致 404 错误。所有单页应用程序(SPA,Single Page Application)框架都必须通过服务器或客户端的某些配置解决这个问题。