JavaScript高级程序设计 第12章---BOM浏览器对象模型
第12章 BOM
本章内容:
- 理解BOM的核心——window 对象
- 控制窗口及弹窗
- 通过location 对象获取页面信息
- 使用navigator 对象了解浏览器
- 通过history 对象操作浏览器历史
BOM是使用JavaScript 开发Web 应用程序的核心,提供了与网页无关的浏览器功能对象。
12.1 window对象
BOM 的核心是window 对象,表示浏览器的实例。window 对象在浏览器中有两重身份,一个是ECMAScript 中的Global 对象,另一个就是浏览器窗口的JavaScript 接口。这意味着网页中定义的所有对象、变量和函数都以window 作为其Global 对象,都可以访问其上定义的parseInt()等全局方法。
12.1.1 Global
因为window 对象被复用为ECMAScript 的Global 对象,所以通过var 声明的所有全局变量和函数都会变成window 对象的属性和方法。
var age = 29;
var sayAge = () => alert(this.age);alert(window.age); // 29
sayAge(); // 29
window.sayAge(); // 29
但如果在这里使用let 或const 替代var,则不会把变量添加给全局对象:
let age = 29;
const sayAge = () => alert(this.age);alert(window.age); // undefined
sayAge(); // undefined
window.sayAge(); // TypeError: window.sayAge is not a function
访问未声明的变量会抛出错误,但是通过属性查询在window对象上查询就不会抛出错误,会返回undefined
// 这会导致抛出错误,因为oldValue 没有声明
var newValue = oldValue;// 这不会抛出错误,因为这里是属性查询
// newValue 会被设置为undefined
var newValue = window.oldValue;
12.1.2 窗口关系
top 对象始终指向最上层(最外层)窗口,即浏览器窗口本身。而parent 对象则始终指向当前窗口的父窗口。如果当前窗口是最上层窗口,则parent 等于top(都等于window)。
还有一个self 对象,它是终极window 属性,始终会指向window。实际上,self 和window 就是同一个对象。之所以还要暴露self,就是为了和top、parent 保持一致。
这些属性都是window 对象的属性,因此访问window.parent、window.top 和window.self都可以。这意味着可以把访问多个窗口的window 对象串联起来,比如window.parent.parent。
12.1.3 窗口位置与像素比
window 对象的位置可以通过不同的属性和方法来确定。现代浏览器提供了screenLeft 和screenTop 属性,用于表示窗口相对于屏幕左侧和顶部的位置 ,返回值的单位是CSS 像素。
可以使用moveTo()
和moveBy()
方法移动窗口。这两个方法都接收两个参数,其中moveTo()
接收要移动到的新位置的绝对坐标x 和y;而moveBy()
则接收相对当前位置在两个方向上移动的像素数。比如:
// 把窗口移动到左上角
window.moveTo(0,0);// 把窗口向下移动100 像素
window.moveBy(0, 100);
操作示例:https://www.runoob.com/try/try.php?filename=try_win_moveby
像素比
CSS 像素是Web 开发中使用的统一像素单位。这样定义像素大小是为了在不同设备上统一标准。比如,低分辨率平板设备上12 像素(CSS 像素)的文字应该与高清4K 屏幕下12 像素(CSS 像素)的文字具有相同大小
即不同设备物理像素大小不一致,为了让它们在相同大小的CSS像素效果下显示一致,物理像素与CSS 像素之间的转换比率由window.devicePixelRatio 属性提供。不同设备有不同的这个属性值来确保显示效果的一致性。(即CSS像素和显示大小保持一致,但物理像素的数量由设备的比例属性来决定)
window.devicePixelRatio 实际上与每英寸像素数(DPI,dots per inch)是对应的。DPI 表示单位像素密度,而window.devicePixelRatio 表示物理像素与逻辑像素之间的缩放系数。
12.1.4 窗口大小
所有现代浏览器都支持4 个属性:
innerWidth、innerHeight、outerWidth 和outerHeight。outerWidth 和outerHeight 返回浏览器窗口自身的大小(不管是在最外层window 上使用,还是在窗格中使用)。innerWidth和innerHeight 返回浏览器窗口中页面视口的大小(不包含浏览器边框和工具栏)。
document.documentElement.clientWidth
和document.documentElement.clientHeight
返回页面视口的宽度和高度(和innerWidth,innerHeight一样)。
例如下面这个页面
页面视口大小和浏览器窗口大小就不一致:
innerWidth
1174
outerWidth
1434
可以使用resizeTo()
和resizeBy()
方法调整窗口大小(直接在f12处输入无反应)。这两个方法都接收两个参数,resizeTo()接收新的宽度和高度值,而resizeBy()接收宽度和高度各要缩放多少。下面看个例子:
// 缩放到100×100
window.resizeTo(100, 100);
// 缩放到200×150
window.resizeBy(100, 50);
// 缩放到300×300
window.resizeTo(300, 300);
与移动窗口的方法一样,缩放窗口的方法可能会被浏览器禁用,而且在某些浏览器中默认是禁用的。同样,缩放窗口的方法只能应用到最上层的window 对象。
12.1.5 视口位置
浏览器窗口尺寸通常无法满足完整显示整个页面,为此用户可以通过滚动在有限的视口中查看文档。度量文档相对于视口滚动距离的属性有两对,返回相等的值:window.pageXoffset/window.scrollX
和window.pageYoffset/window.scrollY
。
可以使用scroll()
、scrollTo()
和scrollBy()
方法滚动页面。这3 个方法都接收表示相对视口距离的x 和y 坐标,这两个参数在前两个方法中表示要滚动到的坐标,在最后一个方法中表示滚动的距离。
// 相对于当前视口向下滚动100 像素
window.scrollBy(0, 100);
// 相对于当前视口向右滚动40 像素
window.scrollBy(40, 0);
// 滚动到页面左上角
window.scrollTo(0, 0);
// 滚动到距离屏幕左边及顶边各100 像素的位置
window.scrollTo(100, 100);
这个可以正常使用
这几个方法也都接收一个ScrollToOptions 字典,除了提供偏移值,还可以通过behavior 属性告诉浏览器是否平滑滚动。
// 正常滚动 即快速跳转
window.scrollTo({left: 100,top: 100,behavior: 'auto'
});// 平滑滚动 即慢慢滚动
window.scrollTo({left: 100,top: 100,behavior: 'smooth'
});
12.1.6 导航与打开新窗口
window.open()
方法可以用于导航到指定URL,也可以用于打开新浏览器窗口。这个方法接收4个参数:要加载的URL、目标窗口、特性字符串和表示新窗口在浏览器历史记录中是否替代当前加载页面的布尔值。通常,调用这个方法时只传前3 个参数,最后一个参数只有在不打开新窗口时才会使用。
如果window.open()的第二个参数target是一个已经存在的窗口或窗格(frame)的名字,则会在对应的窗口或窗格中打开URL。下面是一个例子:
// 与<a href="http://www.wrox.com" target="topFrame"/>相同
window.open("http://www.wrox.com/", "topFrame");
如果存在窗口名(即window.name
)与指定的target值相同的窗口时,在该窗口处打开这个链接;如果不存在满足条件的窗口,就新建一个窗口打开这个链接,并把新窗口的窗口名(window.name
)赋值为指定的target值。
1. 弹出窗口
window.open()方法返回一个对新建窗口的引用。这个对象与普通window 对象没有区别,只是为控制新窗口提供了方便。例如,某些浏览器默认不允许缩放或移动主窗口,但可能允许缩放或移动通过window.open()创建的窗口。跟使用任何window 对象一样,可以使用这个对象操纵新打开的窗口。
let wroxWin = 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();
但自己在尝试时,出现了Blocked a frame with origin
,无法进行操作的问题。
弹出窗口可以调用top.close()
来关闭自己(可以使用)。
关闭窗口以后,窗口的引用虽然还在,但只能用于检查其closed 属性了:
wroxWin.close();
alert(wroxWin.closed); // true
新创建窗口的window 对象有一个属性opener,指向打开它的窗口。这个属性只在弹出窗口的最上层window 对象(top)有定义,是指向调用window.open()打开它的窗口或窗格的指针。例如:
let wroxWin = window.open("http://www.wrox.com/","wroxWindow","height=400,width=400,top=10,left=10,resizable=yes");alert(wroxWin.opener === window); // true
新建窗口中有指向打开它的窗口的指针,但窗口不会跟踪记录自己打开的新窗口,因此开发者需要自己记录。
在某些浏览器中,每个标签页会运行在独立的进程中。如果一个标签页打开了另一个,而window对象需要跟另一个标签页通信,那么标签便不能运行在独立的进程中。在这些浏览器中,可以将新打开的标签页的opener 属性设置为null,表示新打开的标签页可以运行在独立的进程中。比如:
let wroxWin = window.open("http://www.wrox.com/","wroxWindow","height=400,width=400,top=10,left=10,resizable=yes");wroxWin.opener = null;
把opener 设置为null 表示新打开的标签页不需要与打开它的标签页通信,因此可以在独立进程中运行。这个连接一旦切断,就无法恢复了。
即切断一个标签页A和通过它打开的标签页B之间的联系,这样A才能与B进行通信。
2. 安全限制
弹出窗口有段时间被在线广告用滥了。很多在线广告会把弹出窗口伪装成系统对话框,诱导用户点击。因为长得像系统对话框,所以用户很难分清这些弹窗的来源。为了让用户能够区分清楚,浏览器开始对弹窗施加限制。
3. 弹窗屏蔽程序
所有现代浏览器都内置了屏蔽弹窗的程序,因此大多数意料之外的弹窗都会被屏蔽。在浏览器屏蔽弹窗时,可能会发生一些事。如果浏览器内置的弹窗屏蔽程序阻止了弹窗,那么window.open()很可能会返回null。此时,只要检查这个方法的返回值就可以知道弹窗是否被屏蔽了,比如:
let wroxWin = window.open("http://www.wrox.com", "_blank");
if (wroxWin == null){alert("The popup was blocked!");
}
在浏览器扩展或其他程序屏蔽弹窗时,window.open()通常会抛出错误。因此要准确检测弹窗是否被屏蔽,除了检测window.open()的返回值,还要把它用try/catch 包装起来,像这样:
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!");
}
上面这种写法,如果window.open()抛出错误,可以正确运行错误显示程序;或者是返回null,也可以正确运行错误显示程序。
12.1.7 定时器
JavaScript 在浏览器中是单线程执行的,但允许使用定时器指定在某个时间之后或每隔一段时间就执行相应的代码。setTimeout()
用于指定在一定时间后执行某些代码,而setInterval()
用于指定每隔一段时间执行某些代码。
setTimeout()方法通常接收两个参数:要执行的代码和在执行回调函数前等待的时间(毫秒)。第一个参数可以是包含JavaScript 代码的字符串(类似于传给eval()的字符串)或者一个函数,第二个参数是要等待的毫秒数,比如:
// 在1 秒后显示警告框
setTimeout(() => alert("Hello world!"), 1000);
JavaScript 是单线程的,所以每次只能执行一段代码。为了调度不同代码的执行,JavaScript 维护了一个任务队列。其中的任务会按照添加到队列的先后顺序执行。setTimeout()的第二个参数只是告诉JavaScript 引擎在指定的毫秒数过后把任务添加到这个队列。如果队列是空的,则会立即执行该代码。如果队列不是空的,则代码必须等待前面的任务执行完才能执行。
调用setTimeout()时,会返回一个表示该超时排期的数值ID。这个超时ID 是被排期执行代码的唯一标识符,可用于取消该任务。要取消等待中的排期任务,可以调用clearTimeout()
方法并传入超时ID,如下面的例子所示:
// 设置超时任务
let timeoutId = setTimeout(() => alert("Hello world!"), 1000);
// 取消超时任务
clearTimeout(timeoutId);
只要是在指定时间到达之前调用clearTimeout(),就可以取消超时任务。在任务执行后再调用clearTimeout()没有效果。
注意
所有超时执行的代码(函数)都会在全局作用域中的一个匿名函数中运行,因此函数中的this
值在非严格模式下始终指向window
,而在严格模式下是undefined。如果给setTimeout()
提供了一个箭头函数,那么this
会保留为定义它时所在的词汇作用域。
setInterval()同样可以接收两个参数:要执行的代码(字符串或函数),以及把下一次执行定时代码的任务添加到队列要等待的时间(毫秒)。指定的任务会每隔指定时间就执行一次,直到取消循环定时或者页面卸载。
页面卸载:
在JavaScript中,这个事件在从当前浏览器窗口内移动文档的位置时触发,也就是说,通过超链接、前进或后退按钮等方式词能够一个页面跳转到其他页面,或者关闭浏览器窗口时触发。
setInterval(() => alert("Hello world!"), 10000);
注意
这里的关键点是,第二个参数,也就是间隔时间,指的是向队列添加新任务之前等待的时间。比如,调用setInterval()的时间为01:00:00,间隔时间为3000毫秒。这意味着01:00:03 时,浏览器会把任务添加到执行队列。浏览器不关心这个任务什么时候执行或者执行要花多长时间。因此,到了01:00:06,它会再向队列中添加一个任务。由此可看出,执行时间短、非阻塞的回调函数比较适合setInterval()。
setInterval()方法也会返回一个循环定时ID,可以用于在未来某个时间点上取消循环定时。要取消循环定时,可以调用clearInterval()
并传入定时ID。
通过setInterval()方法实现一个定时增加,并在满足条件后停止的功能:
let num = 0, intervalId = null;
let max = 10;
let incrementNumber = function() {num++;// 如果达到最大值,则取消所有未执行的任务if (num == max) {clearInterval(intervalId);alert("Done");}
}intervalId = setInterval(incrementNumber, 500);
在这个例子中,变量num 会每半秒递增一次,直至达到最大限制值。此时循环定时会被取消。这个模式也可以使用setTimeout()来实现,比如:
let num = 0;
let max = 10;
let incrementNumber = function() {num++;// 如果还没有达到最大值,再设置一个超时任务if (num < max) {setTimeout(incrementNumber, 500);} else {alert("Done");}
}setTimeout(incrementNumber, 500);
注意在使用setTimeout()时,不一定要记录超时ID,因为它会在条件满足时自动停止。。这个模式是设置循环任务的推荐做法。setIntervale()在实践中很少会在生产环境下使用,因为一个任务结束和下一个任务开始之间的时间间隔是无法保证的,有些循环定时任务可能会因此而被跳过。而像前面这个例子中一样使用setTimeout()则能确保不会出现这种情况。一般来说,最好不要使用setInterval()。
12.1.8 系统对话框
使用alert()
、confirm()
和prompt()
方法,可以让浏览器调用系统对话框向用户显示消息。
这些对话框与浏览器中显示的网页无关,而且也不包含HTML。它们的外观由操作系统或者浏览器决定,无法使用CSS 设置。此外,这些对话框都是同步的模态对话框,即在它们显示的时候,代码会停止执行,在它们消失以后,代码才会恢复执行。
警告框
alert()
方法接收一个要显示给用户的字符串。与console.log
可以接收任意数量的参数且能一次性打印这些参数不同,alert()只接收一个参数。调用alert()时,传入的字符串会显示在一个系统对话框中。对话框只有一个“OK”(确定)按钮。如果传给alert()的参数不是一个原始字符串,则会调用这个值的toString()方法将其转换为字符串。
确认框
通过调用confirm()
来显示确认框。确认框跟警告框类似,都会向用户显示消息。但不同之处在于,确认框有两个按钮:“Cancel”(取消)和“OK”(确定)。用户通过单击不同的按钮表明希望接下来执行什么操作。
要知道用户单击了OK 按钮还是Cancel 按钮,可以判断confirm()方法的返回值:true 表示单击了OK 按钮,false 表示单击了Cancel 按钮或者通过单击某一角上的X 图标关闭了确认框。确认框的典型用法如下所示:
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()
方法来显示。提示框的用途是提示用户输入消息。
除了OK 和Cancel 按钮,提示框还会显示一个文本框,让用户输入内容。prompt()方法接收两个参数:要显示给用户的文本,以及文本框的默认值(可以是空字符串,即输入框处会显示的提示字符)
如果用户单击了OK 按钮,则prompt()会返回文本框中的值。如果用户单击了Cancel 按钮,或者对话框被关闭,则prompt()会返回null。下面是一个例子:
let text = prompt('请输入你想输入的信息:', '这里是提示字符')
这些系统对话框可以向用户显示消息、确认操作和获取输入。由于不需要HTML 和CSS,所以系统对话框是Web 应用程序最简单快捷的沟通手段。
12.2 location对象
location提供了当前窗口中加载文档的信息,以及通常的导航功能。
这个对象独特的地方在于, 它既是window 的属性, 也是document 的属性。也就是说,window.location
和document.location
指向同一个对象。location 对象不仅保存着当前加载文档的信息,也保存着把URL 解析为离散片段后能够通过属性访问的信息。这些解析后的属性在P372中有详细说明(location 前缀是必需的)。
12.2.1 查询字符串
location.search
返回了从问号开始直到URL 末尾的所有内容。即如果当前的URL中包含问号字符,就会返回问号开始直到URL末尾的字符串。
示例:
https://editor.csdn.net/md?articleId=119905546location.search
// "?articleId=119905546"
URL中符号的作用: 网址后面用?/&等符号引导的语句有什么功能?
/
相对路径?
路径与参数分隔符&
参数之间的分隔符
因为获取的参数是连在一起的,因此需要将它们拆分开进行使用:
1. 自定义拆分函数
let getQueryStringArgs = function() {// 取得没有开头问号的查询字符串let qs = (location.search.length > 0 ? location.search.substring(1) : ""),// 保存数据的对象args = {};// 把每个参数添加到args 对象for (let item of qs.split("&").map(kv => kv.split("="))) {let name = decodeURIComponent(item[0]),value = decodeURIComponent(item[1]);if (name.length) {args[name] = value;}}return args;
}
这里location.search.substring(1)
表示的是从下标1开始的原字符串,即去掉了location.search
返回的字符串中的首字符?
,
qs.split("&").map(kv => kv.split("="))
再按照&分割成,再利用map函数利用等号分割并以数组返回。
split返回一个分割产生的数组,再利用map将数组中的每个元素kv再利用等号分割并映射为一个子数组(即数组中元素也是数组)。
let name = decodeURIComponent(item[0]),value = decodeURIComponent(item[1]);
item表示的是子数组,利用下标读取子数组中的每个元素。实现了对URL中参数名及对应参数值的读取。
因为查询字符串通常是被编码后的格式,所以使用decodeURIComponent()
解码
使用这个函数:
// 假设查询字符串为?q=javascript&num=10
let args = getQueryStringArgs();alert(args["q"]); // "javascript"
alert(args["num"]); // "10"
2. URLSearchParams
URLSearchParams
提供了一组标准API 方法,通过它们可以检查和修改查询字符串。给URLSearchParams 构造函数传入一个查询字符串,就可以创建一个实例。这个实例上暴露了get()、set()和delete()等方法,可以对查询字符串执行相应操作。
即可以直接使用这个API来进行参数值的读取,不需要自己进行定义。
示例:
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"
可以使用读取,还能进行添加删除对应参数的操作。
还可以当作迭代对象进行参数名参数值的访问:
let qs = "?q=javascript&num=10";let searchParams = new URLSearchParams(qs);for (let param of searchParams) {console.log(param);
}
// ["q", "javascript"]
// ["num", "10"]
12.2.2 操作地址
可以通过修改location 对象修改浏览器的地址。即都是在当前页面进行跳转。
方法1. assign()方法
最常见的是使用assign()
方法并传入一个URL
location.assign("http://www.wrox.com");
这行代码会立即启动导航到新URL 的操作(当前页面直接进行跳转),同时在浏览器历史记录中增加一条记录。
方法2. location.href 或window.location
location.href
或window.location
设置一个URL,也会以同一个URL 值调用assign()方法。比如,下面两行代码都会执行与显式调用assign()一样的操作:
window.location = "http://www.wrox.com";
location.href = "http://www.wrox.com";
方法3. 修改location的属性
修改location 对象的属性也会修改当前加载的页面。其中,hash
、search
、hostname
、pathname
和port
属性被设置为新值之后都会修改当前URL
在以前面提到的3种方式修改URL 之后,浏览器历史记录中就会增加相应的记录。当用户单击“后退”按钮时,就会导航到前一个页面。
方法4. 不会留下历史记录:replace()方法
如果不希望增加历史记录,可以使用replace()
方法。这个方法接收一个URL 参数,但重新加载后不会增加历史记录。调用replace()
之后,用户不能回到前一页。
<!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。
方法5. 重新加载当前显示的页面:reload()
reload()
,它能重新加载当前显示的页面。调用reload()
而不传参数,页面会以最有效的方式重新加载。也就是说,如果页面自上次请求以来没有修改过,浏览器可能会从缓存中加载页面。如果想强制从服务器重新加载,可以像下面这样给reload()
传个true:
location.reload(); // 重新加载,可能是从缓存加载
location.reload(true); // 重新加载,从服务器加载
脚本中位于reload()调用之后的代码可能执行也可能不执行,这取决于网络延迟和系统资源等因素。为此,最好把reload()作为最后一行代码。
12.3 navigator 对象
是客户端标识浏览器的标准。
只要浏览器启用JavaScript,navigator 对象就一定存在。但是与其他BOM对象一样,每个浏览器都支持自己的属性。
navigator 对象的属性通常用于确定浏览器的类型。
12.3.1 检测插件
通过plugins 数组来检测浏览器是否安装了某个插件,这个数组中的每一项都包含如下属性。
- name:插件名称。
- description:插件介绍。
- filename:插件的文件名。
- length:由当前插件处理的MIME 类型数量
console.log(window.navigator.plugins)
// PluginArray {0: Plugin, 1: Plugin, 2: Plugin, Chrome PDF Plugin: Plugin, Chrome PDF Viewer: Plugin, Native Client: Plugin, length: 3}
检测是否有指定的插件。
// 插件检测,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"));
首先不管是输入还是浏览器中的插件名都变成小写,便于比较避免大小写问题。使用indexOf来判断是否存在指定插件。
IE10 及更低版本中检测插件的问题比较多,所以需要别的方法来检测插件。
12.3.2 注册处理程序
现代浏览器支持navigator 上的(在HTML5 中定义的)registerProtocolHandler()方法。这个方法可以把一个网站注册为处理某种特定类型信息应用程序。随着在线RSS 阅读器和电子邮件客户端的流行,可以借助这个方法将Web 应用程序注册为像桌面软件一样的默认应用程序。
12.4 screen对象
window 的另一个属性screen 对象,是为数不多的几个在编程中很少用的JavaScript 对象。这个对象中保存的纯粹是客户端能力信息,也就是浏览器窗口外面的客户端显示器的信息,比如像素宽度和像素高度。每个浏览器都会在screen 对象上暴露不同的属性。
12.5 history对象
history 对象表示当前窗口首次使用以来用户的导航历史记录。因为history 是window 的属性,所以每个window 都有自己的history 对象。出于安全考虑,这个对象不会暴露用户访问过的URL,但可以通过它在不知道实际URL 的情况下前进和后退。
12.5.1 导航
go()
方法可以在用户历史记录中沿任何方向导航,可以前进也可以后退。这个方法只接收一个参数,这个参数可以是一个整数,表示前进或后退多少步。负值表示在历史记录中后退(类似点击浏览器的“后退”按钮),而正值表示在历史记录中前进(类似点击浏览器的“前进”按钮)。
// 后退一页
history.go(-1);
// 前进一页
history.go(1);
// 前进两页
history.go(2);
在旧版本的一些浏览器中,go()方法的参数也可以是一个字符串,这种情况下浏览器会导航到历史中包含该字符串的第一个位置。最接近的位置可能涉及后退,也可能涉及前进。如果历史记录中没有匹配的项,则这个方法什么也不做,如下所示:
// 导航到最近的wrox.com 页面
history.go("wrox.com");
// 导航到最近的nczonline.net 页面
history.go("nczonline.net");
go()有两个简写方法:back()
和forward()
。顾名思义,这两个方法模拟了浏览器的后退按钮和前进按钮:
// 后退一页
history.back();
// 前进一页
history.forward();
history 对象还有一个length
属性,表示历史记录中有多个条目。这个属性反映了当前页面的历史记录的数量,包括可以前进和后退的页面。对于窗口或标签页中加载的第一个页面,history.length
等于1。通过以下方法测试这个值,可以确定用户浏览器的起点是不是你的页面:
if (history.length == 1){// 这是用户窗口中的第一个页面
}
12.5.2 历史状态管理
即在不加载新页面的时候改变浏览器URL。P380
小结
浏览器对象模型(BOM,Browser Object Model)是以window 对象为基础的,这个对象代表了浏览器窗口和页面可见的区域。window 对象也被复用为ECMAScript 的Global 对象,因此所有全局变量和函数都是它的属性,而且所有原生类型的构造函数和普通函数也都从一开始就存在于这个对象之上。本章讨论了BOM 的以下内容。
- 要引用其他window 对象,可以使用几个不同的窗口指针。
- 通过location 对象可以以编程方式操纵浏览器的导航系统。通过设置这个对象上的属性,可 以改变浏览器URL 中的某一部分或全部。
- 使用replace()方法可以替换浏览器历史记录中当前显示的页面,并导航到新URL。
- navigator 对象提供关于浏览器的信息。提供的信息类型取决于浏览器,不过有些属性如 userAgent 是所有浏览器都支持的。
BOM 中的另外两个对象也提供了一些功能。screen 对象中保存着客户端显示器的信息。这些信息通常用于评估浏览网站的设备信息。history 对象提供了操纵浏览器历史记录的能力,开发者可以确定历史记录中包含多少个条目,并以编程方式实现在历史记录中导航,而且也可以修改历史记录。
JavaScript高级程序设计 第12章---BOM浏览器对象模型相关推荐
- JavaScript高级程序设计 第12章 DOM2 和 DOM3
12.2 样式 12.2.1 访问元素样式 通过 JavaScript 访问 style 中的样式要使用驼峰命名法 其中,不能直接转换的样式是 float,"DOM2级样式"规定的 ...
- 攻下《JavaScript高级程序设计》——第二章 在HTML中使用JavaScript
从上一章我们知道了,JavaScript是一种专门为网页交互而设计的脚本语言,那么,它就免不了和HTML打交道,所以在设计JavaScript的时候,Netscape首要面临的就是,怎么让HTML和J ...
- 打码进行中-JavaScript高级程序设计-第1章-什么是javaScript
1.1简短的历史回顾 输入验证 网景 微软 欧洲计算机制造商协会(Ecma) ECMAScript 1.2JavaScript实现 完整的JavaScript实现包含以下几个部分: 核心(ECMASc ...
- JavaScript高级程序设计 第四章---变量 作用域 内存
第四章-变量 作用域 内存 关键字:变量 作用域 内存 本章内容 通过变量使用原始值与引用值 理解执行上下文 理解垃圾回收 4.1 原始值与引用值 ECMAScript 变量可以包含两种不同类型的数据 ...
- JavaScript高级程序设计---第五章 基本引用类型
第五章 基本引用类型 本章内容 理解对象 基本JavaScript 数据类型 原始值与原始值包装类型 引用值(或者对象)是某个特定引用类型的实例. 对象被认为是某个特定引用类型的实例.新对象通过使用n ...
- JavaScript高级程序设计第六章---集合引用类型
第六章-集合引用类型 本章内容: 对象 数组与定型数组 Map.WeakMap.Set 以及WeakSet 类型 6.1 Object 显式地创建Object 的实例有两种方式: 使用new 操作符和 ...
- JavaScript 高级程序设计第四章解读,总结。
第四章 变量,作用域与内存 通过变量使用原始值 - 1. 原始值与引用值+ 原始值: 最简单的数据+ 引用值: 多个值构成的对象 - 2. 原始值有哪些+ Undefined Null Boolean ...
- JavaScript 高级程序设计第二章
第二章 教材: JavaScript 高级程序设计 目录 第二章 一. script元素 1. 介绍 2. 标签位置 2.1. 推迟执行脚本---defer属性 2.2. 异步执行脚本---async ...
- 《JavaScript高级程序设计》读书笔记 -12.1 window对象
<JavaScript高级程序设计>读书笔记 -12.1 window对象 12.1 window对象 12.1.1 Global作用域 12.1.2 窗口关系[不是很懂] 12.1.3 ...
最新文章
- c语言程序设计家庭收支类,家庭支出管理系统—c语言程序设计
- Java怎么重复使用套接字_在java中连续地通过套接字传输数据
- 嗨,你选择自学成才还是参加培训?
- android shape 自定义,Android自定义shape的使用
- ubuntu 14 java web服务器搭建
- Google的电话面试
- VUE2.0增删改查附编辑添加model(弹框)组件共用
- https://docs.python.org/3/
- 网路游侠:某硬件WEB应用防火墙配置图示
- Linux下安装PHP扩展
- 详解YUV数据格式(YUV444,YUV422,YUV420,YV12,YU12,NV12,NV21)
- Excel多个工作簿合成为一个工作表
- HDU - 4960 Another OCD Patient 真实的DP
- 使用Mailgun Store():应用程序传入电子邮件的临时邮箱
- 叙述两个计算机技术的应用,《计算机技术与应用基础》复习题附答案.doc
- Mac设置chrome浏览器跨域
- RTSP,Java实现简单的RTSP报文交换
- 多亏了这些Word技巧,我才能15分钟完成所有工作!真是6到飞起
- 数字图像处理——第十章(图像分割)
- NEON intrinsic 简易入门指南
热门文章
- Tribon数据库结构研究
- 如何养成高效的好习惯?
- EMC XtremIO“死亡传闻”被质疑
- 云南大学计算机专业双一流排名,双一流211大学 云南大学2020年各省各批次专业录取分数线...
- 硬件视频编解码基本知识
- 时钟定义篇 - 附CREATE_GENERATED_CLOCK花式定义方法
- error Command failed.报错问题解决(Linux下/Windows下)
- java梅森素数,C语言求梅森素数代码及解析
- 计算机信息技术发展方向,谈谈计算机信息技术发展方向及应用
- c语言怎么产生随机数函数,详细介绍一下C语言里面的随机数产生函数random怎么用...