BOM(Browser Object Model)浏览器对象模型,BOM 是使用 JavaScript 开发 Web 应用程序的核心。

1. window 对象

BOM 的核心是 window 对象,表示浏览器的实例。
window 对象在浏览器中有两重身份,一个是ES 中的 Global 对象,另一个就是浏览器窗口的 JavaScript 接口。

1.1 Global 作用域

由于 window 对象被复用为 ECMAScript 的 Global 对象
所以通过 var 声明的所有全局变量和函数都会变成 window 对象的属性和方法。
例如:

  1. var age = 29;
  2. var sayAge = () => alert(this.age);
  3. alert(window.age); // 29
  4. sayAge(); // 29
  5. window.sayAge(); // 29

如果使用 let 或 const 替代 var,则不会添加给全局对象

  1. let age = 29;
  2. const sayAge = () => alert(this.age);
  3. alert(window.age); // undefined
  4. sayAge(); // undefined
  5. window.sayAge(); // TypeError: window.sayAge is not a function

另外,可以在 window 对象上查询是否存在可能未声明的变量。

1.2 窗口关系

  • top 对象始终指向最上层窗口,即浏览器窗口本身。
  • parent 对象则始终指向当前窗口的父窗口。
    如果当前窗口是最上层窗口,则 parent 等于 top(都等于 window)
  • self 对象是终极 window 属性,始终会指向 window。

1.3 窗口位置与像素比

screenLeft 和screenTop 属性

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

moveTo()和 moveBy()方法

作用:可以移动窗口

  • moveTo()接收要移动到的新位置的绝对坐标 x 和 y;
  • moveBy()则接收相对当前位置在两个方向上移动的像素数。

像素比

举个例子,手机屏幕的物理分辨率可能是 1920×1080,但因为其像素可能非常小,所以浏览器就需
要将其分辨率降为较低的逻辑分辨率,比如 640×320。这个物理像素与 CSS 像素之间的转换比率由
window.devicePixelRatio 属性提供。
window.devicePixelRatio 实际上与每英寸像素数(DPI,dots per inch)是对应的。

1.4 窗口大小

4个属性:innerWidth、innerHeight、outerWidth 和 outerHeight

  • innerWidth、innerHeight 返回浏览器窗口中页面视口的大小(不包含浏览器边框和工具栏)
  • outerWidth 和 outerHeight 返回浏览器窗口自身的大小
  • document.documentElement.clientWidth 和document.documentElement.clientHeight返回页面视口的宽度和高度。

确定页面视口的大小:

  1. let pageWidth = window.innerWidth,
  2. pageHeight = window.innerHeight;
  3. if (typeof pageWidth != "number") {
  4. if (document.compatMode == "CSS1Compat"){
  5. pageWidth = document.documentElement.clientWidth;
  6. pageHeight = document.documentElement.clientHeight;
  7. } else {
  8. pageWidth = document.body.clientWidth;
  9. pageHeight = document.body.clientHeight;
  10. }
  11. }

调整窗口大小

可以使用resizeTo()和resizeBy()方法

  1. // 缩放到 100×100
  2. window.resizeTo(100, 100);
  3. // 缩放到 200×150
  4. window.resizeBy(100, 50);
  5. // 缩放到 300×300
  6. window.resizeTo(300, 300);

1.5 视口位置

scroll()、scrollTo()和 scrollBy()方法滚动页面

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

也可以接收一个ScrollToOptions字典,通过 behavior 属性告诉浏览器是否平滑滚动。

  1. // 正常滚动
  2. window.scrollTo({
  3. left: 100,
  4. top: 100,
  5. behavior: 'auto'
  6. });
  7. // 平滑滚动
  8. window.scrollTo({
  9. left: 100,
  10. top: 100,
  11. behavior: 'smooth'
  12. });

1.6 导航与打开新窗口

windo.open()接收4个参数
要加载的 URL、目标窗口、特性字符串和表示新窗口在浏览器历史记录中是否替代当前加载页
面的布尔值。

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

1.6.1 弹出窗口

如果window.open()的第二个参数不是已有窗口,则会打开一个新窗口或标签页。
第三个参数,特性字符串是一个逗号分隔的设置字符串
【BOM】 - 图1
【BOM】 - 图2

  1. window.open("http://www.wrox.com/",
  2. "wroxWindow",
  3. "height=400,width=400,top=10,left=10,resizable=yes");
  • window.open()方法返回一个对新建窗口的引用。与window对象一样。
  • close()方法可以关闭新打开的窗口。
  • 把 opener 设置为 null 表示新打开的标签页不需要与打开它的标签页通信,因此可以在独立进程中运行
  1. let wroxWin = window.open("http://www.wrox.com/",
  2. "wroxWindow",
  3. "height=400,width=400,top=10,left=10,resizable=yes");
  4. wroxWin.opener = null;

1.6.2 弹窗屏蔽程序

window.open()返回null则弹窗被屏蔽

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

1.7 定时器

1.7.1 setTimeout()方法

setTimeout()用于指定在一定时间后执行某些代码
两个参数

  • 1.要执行的代码:可以是字符串包含的代码,也可以是一个函数。
  • 2.执行回调函数前等待的时间(毫秒)
  1. // 在 1 秒后显示警告框
  2. setTimeout(() => alert("Hello world!"), 1000);

在指定时间到达之前调用clearTimeout(),可以取消超时任务

  1. // 设置超时任务
  2. let timeoutId = setTimeout(() => alert("Hello world!"), 1000);
  3. // 取消超时任务
  4. clearTimeout(timeoutId);

setInterval()方法

setInterval()用于指定每隔一段时间执行某些代码。
和setTimeout()方法同样是接收两个参数

注意:这两个函数都不关心代码什么时候执行,只关心代码什么时候加入执行队列,当队列排到这个代码时才会执行。

取消定时,clearInterval()方法
  1. let num = 0, intervalId = null;
  2. let max = 10;
  3. let incrementNumber = function() {
  4. num++;
  5. // 如果达到最大值,则取消所有未执行的任务
  6. if (num == max) {
  7. clearInterval(intervalId);
  8. alert("Done");
  9. }
  10. }
  11. intervalId = setInterval(incrementNumber, 500);

在实际开发中推荐用setTimeout()实现,因为一个任务结束和下一个任务开始之间的时间间隔是无法保证的。可以改成下面代码:

  1. let num = 0;
  2. let max = 10;
  3. let incrementNumber = function() {
  4. num++;
  5. // 如果还没有达到最大值,再设置一个超时任务
  6. if (num < max) {
  7. setTimeout(incrementNumber, 500);
  8. } else {
  9. alert("Done");
  10. }
  11. }
  12. setTimeout(incrementNumber, 500);

系统对话框

alert()、confirm()和 prompt()方法,调用系统对话框向用户显示消息

  • 警告框(alert)通常用于向用户显示一些他们无法控制的消息
  • 确认框confirm(),确认框有两个按钮:“Cancel”(取消)和“OK”(确定)
  1. if (confirm("Are you sure?")) {
  2. alert("I'm so glad you're sure!");
  3. } else {
  4. alert("I'm sorry to hear you're not sure.");
  5. }
  • 提示框prompt()
  1. let result = prompt("What is your name? ", "");
  2. if (result !== null) {
  3. alert("Welcome, " + result);
  4. }

2. location 对象

location提供了当前窗口中加载文档的信息,以及通常的导航功能
既是 window 的属性,也是 document 的属性.
【BOM】 - 图3

2.1 查询字符串

URL 中的查询字符串并不容易使用,手动操作代码:

  1. let getQueryStringArgs = function() {
  2. // 取得没有开头问号的查询字符串
  3. let qs = (location.search.length > 0 ? location.search.substring(1) : ""),
  4. // 保存数据的对象
  5. args = {};
  6. // 把每个参数添加到 args 对象
  7. for (let item of qs.split("&").map(kv => kv.split("="))) {
  8. let name = decodeURIComponent(item[0]),
  9. value = decodeURIComponent(item[1]);
  10. if (name.length) {
  11. args[name] = value;
  12. }
  13. }
  14. return args;
  15. }

现在,URLSearchParams 提供了一组标准 API 方法
给URLSearchParams 构造函数传入一个查询字符串,就可以创建一个实例。这个实例上暴露了 get()、set()和 delete()等方法

  1. let qs = "?q=javascript&num=10";
  2. let searchParams = new URLSearchParams(qs);
  3. alert(searchParams.toString()); // " q=javascript&num=10"
  4. searchParams.has("num"); // true
  5. searchParams.get("num"); // 10
  6. searchParams.set("page", "3");
  7. alert(searchParams.toString()); // " q=javascript&num=10&page=3"
  8. searchParams.delete("q");
  9. alert(searchParams.toString()); // " num=10&page=3"

2.2 操作地址

assign()方法并传入一个 URL

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

给location.href 或 window.location 设置一个 URL,都会执行与显式调用 assign()一样的操作:

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

hash、search、hostname、pathname和 port 属性被设置为新值之后都会修改当前 URL,

2.2.1 replace()方法

调用 replace()之后,用户不能回到前一页
“后退”按钮是禁用状态

3. navigator 对象

navigator 对象的属性通常用于确定浏览器的类型。
用处好像不大,暂且放一放

4.history 对象

4.1 导航

  1. // 后退一页
  2. history.go(-1);
  3. // 前进一页
  4. history.go(1);
  5. // 前进两页
  6. history.go(2);
  1. // 导航到最近的 wrox.com 页面
  2. history.go("wrox.com");
  3. // 导航到最近的 nczonline.net 页面
  4. history.go("nczonline.net");
  1. // 后退一页
  2. history.back();
  3. // 前进一页
  4. history.forward();