• BOM的核心是window对象,表示浏览器的实例。
  • window对象在浏览器中有两重身份:
    • ECMAScript中的Global对象;
    • 浏览器窗口的JavaScript接口。

Global作用域

  • window对象被复用为ECMAScript的Global对象;
  • 通过var声明的所有全局变量和函数都会变成window对象的属性和方法。
  • 使用let 或const替代var,则不会把变量添加给全局对象。
1
2
3
4
5
6
7
8
9
10
11
var age = 29; 
var sayAge = () => alert(this.age);
alert(window.age); // 29
sayAge(); // 29
window.sayAge(); // 29
//=========================
let age = 29;
const sayAge = () => alert(this.age);
alert(window.age); // undefined
sayAge(); // undefined
window.sayAge(); // TypeError: window.sayAge is not a function
  • 访问未声明的变量会抛出错误,但是可以在window对象上查询是否存在可能未声明的变量。
1
2
3
4
5
// 这会导致抛出错误,因为 oldValue 没有声明
var newValue = oldValue;
// 这不会抛出错误,因为这里是属性查询
// newValue 会被设置为 undefined
var newValue = window.oldValue;

窗口关系

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

窗口位置与像素比

  • window对象的位置可以通过不同的属性和方法来确定:
    • screenLeft和screenTop属性,用于表示窗口相对于屏幕左侧和顶部的位置,返回值的单位是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);

窗口大小

  • outerWidth 和 outerHeight返回浏览器窗口自身大小。
  • innerWidth 和innerHeight返回浏览器窗口中页面视口的大小(不包含浏览器边框和工具栏)
  • document.documentElement.clientWidth和document. documentElement.clientHeight返回页面视口的宽度和高度。
  • 浏览器窗口自身的精确尺寸不好确定,但可以确定页面视口的大小:
1
2
3
4
5
6
7
8
9
10
11
let 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;
}
}

这里,先将 pagewidth 和 pageHeight 的值分别设置为window.innerwidth和 window.innerHeight。然后,检查 pagewidth是不是一个数值,如果不是则通过document.compatMode来检查页面是否处于标准模式。如果是,则使用document.documentElement.clientwidth 和 document.documentElement.clientHeight;否则,就使用document.body.clientwidth和document.body.clientHeight。

  • 在移动设备上,window.innerwidth和window.innerHeight返回视口的大小,也就是屏幕上页面可视区域的大小。Mobile Internet Explorer支持这些属性,但在 document.documentElement.clientwidth和 document.documentElement.clientHeight中提供了相同的信息。在放大或缩小页面时,这些值也会相应变化。
  • 在其他移动浏览器中, document.documentElement.clientWidth和document.documentElement.clientHeight返回的布局视口的大小,即渲染页面的实际大小。布局视口是相对于可见视口的概念,可见视口只能显示整个页面的一小部分。Mobile Internet Explorer 把布局视口的信息保存在document.body.clientwidth和document.body.clientHeight中。在放大或缩小页面时,这些值也会相应变化。

视口位置

  • 浏览器窗口尺寸通常无法满足完整显示整个页面,为此用户可以通过滚动在有限的视口中查看文档。
  • 度量文档相对于视口滚动距离的属性有两对,返回相等的值:window.pageXoffset/window.scrollx和window.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);
  • 这几个方法也都接收一个 scrollTo0ptions 字典,除了提供偏移值,还可以通过behavior属性告诉浏览器是否平滑滚动。
1
2
3
4
5
6
7
8
9
10
11
12
// 正常滚动 
window.scrollTo({
left: 100,
top: 100,
behavior: 'auto'
});
// 平滑滚动
window.scrollTo({
left: 100,
top: 100,
behavior: 'smooth'
});

导航与打开新窗口

  • window.open()方法可以用于导航到指定URL,也可以用于打开新浏览器窗口。方法接收4个参数:
    • 要加载的URL;
    • 目标窗口;如果是一个已存在的窗口或窗格的名字,则会在对应的窗口或窗格中打开URL;如果不是则会打开一个新窗口或标签页
    • 特性字符串;用于指定新窗口的配置,如果没有指定则新窗口会带有所有默认的浏览器特性,如果打开的不是新窗口则忽略。
    • 表示新窗口在浏览器历史记录中是否替代当前加载页面的布尔值。
1
2
3
4
5
// 与<a href="http://www.wrox.com" target="topFrame"/>相同
window.open("http://www.wrox.com/", "topFrame");
/**
执行这行代码的结果就如同用户点击了一个href 属性为"http://www.wrox.com",target属性为"topFrame"的链接。如果有一个窗口名叫"topPrame",则这个窗口就会打开这个 URL;否则就会打开一个新窗口并将其命名为"topFrame"。第二个参数也可以是一个特殊的窗口名,比如_self、_parent、 _top或_blank。
**/

定时器

  • setTimeout()用于指定在一定时间后执行某些代码。
    • 接收两个参数:要执行的代码和执行回调函数前等待的时间。
    • 第一个参数可以是包含JavaScript代码的字符串或者一个函数;
    • 第二个参数是要等待的毫秒数,告诉JavaScript引擎在指定的毫秒数过后把任务添加到这个队列。
    • 返回一个表示该超时排期的数值ID
  • setInterval()用于指定每隔一段时间执行某些代码。
    • 接收两个参数:要执行的代码(字符串或函数)和下一次执行定时代码的任务添加到队列要等待的时间。
    • 第二个参数指的是向队列添加新任务之前等待的时间。
    • 执行时间短、非阻塞的回调函数比较合适。
    • 返回一个循环定时ID,可以用于在未来某个时间点上取消循环定时。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
let num = 0; 
let max = 10;
let incrementNumber = function() {
num++;
// 如果还没有达到最大值,再设置一个超时任务
if (num < max) {
setTimeout(incrementNumber, 500);
} else {
alert("Done");
}
}
setTimeout(incrementNumber, 500);
//==================================
/*
在这个例子中,变量num 会每半秒递增一次,直至达到最大限制值。此时循环定时会被取消。
*/
let num = 0, intervalId = null;
let max = 10;
let incrementNumber = function() {
num++;
// 如果达到最大值,则取消所有未执行的任务
if (num == max) {
clearInterval(intervalId);
alert("Done");
}
}
intervalId = setInterval(incrementNumber, 500);

系统对话框

  • 使用alert()、confirm()和prompt()方法,可以让浏览器调用系统对话框向用户显示消息。
  • 这些对话框与浏览器中显示的网页无关,也不包含HTML。
  • 这些对话框都是同步的模态对话框,即在它们显示的时候,代码会停止执行,在它们消失以后,代码才会恢复执行。
  • alert()方法:消息框
    • 接收一个要显示给用户的字符串。
    • 只接受一个参数。
    • 只有一个按钮(OK/确认)
    • 如果传入的参数不是一个原始字符串,则会调用这个值的toString()方法转换为字符串。
  • confirm()方法:确认框
    • 两个按钮(OK/确认,Cancel/取消)。
    • 返回一个布尔值,OK/确认➡true,Cancel/取消➡false。
  • prompt()方法:提示框
    • 两个按钮(OK/确认,Cancel/取消)和文本框(允许用户输入内容)。
    • 接收两个参数:要显示给用户的文本以及文本框的默认值。