本章内容
- 理解
window
对象--BOM 的核心 - 控制窗口,框架和弹出窗口
- 利用
location
对象中的页面信息 - 使用
navigator
对象了解浏览器
8.1 window 对象
BOM
的核心对象是window
,它表示浏览器的一个实例。在浏览器中,window
对象有双重角色,它既是通过JavaScript
访问浏览器窗口的一个接口,又是 ECMAScript 规定的Global
对象。这意味着在网页中定义的任何一个对象,变量和函数,都以window
作为其Global
对象,因此有权访问parseInt()
等方法。
8.1.1 全局作用域
所有在全局作用域中声明的变量,函数都会变成window
对象的属性和方法。
抛开全局变量会成为window
对象的属性不谈,定义全局变量与在window
对象上直接定义属性还是有一点差别:全局变量不能通过delete
操作符删除,而直接在window
对象上的定义的属性可以。
另外,还要记住一件事:尝试访问未声明的变量会抛出错误,但是通过查询window
对象,可以知道某个可能未声明的变量是否存在。
//这里会抛出错误,因为`oldValue`未定义
var newValue = oldValue;
//这里不会抛出错误,因为这是一次属性查询
//newValue 的值是 undefined
var newValue = window.oldValue;
8.1.2 窗口关系及框架
如果页面中包含框架,则每个框架都有自己的 window
对象,并且保存在frames
集合中。在frames
集合中,可以通过数值索引或者框架名称来访问相应的window
对象。每个window
对象都有一个name
属性,其中包含框架的名称。
top
对象始终指向最高(最外)层的框架。也就是浏览器窗口。使用它可以确保在一个框架中正确地访问另一个框架。因为对于在一个框架中编写的任何代码来说,其中的window
对象指向的都是那个框架的特定实例,而非最高层的框架。
8.1.3 窗口位置
var leftPos = (typeof window.screenLeft == "number") ? window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == "number") ? window.screenTop : window.screenY;
8.1.4 窗口大小
outerWidth
和outerHeight
返回浏览器窗口本身的尺寸;而innerWidth
和innerHeight
则表示该容器中页面视图区的大小(减去边框宽度)。
document.documentElement.clientWidth
和document.documentElement.clientHeight
;document.body.clientWidth
和document.body.clientHeight
。
8.1.5 导航和打开窗口
使用window.open()
方法既可以导航到一个特定的 URL,也可以打开一个新的浏览器窗口。这个方法可以接收 4 个参数:要加载的 URL、窗口目标、一个特性字符串以及一个表示新页面是否取代浏览器历史纪录中当前加载页面的布尔值。通常只需传递第一个参数,最后一个参数只在不打开新窗口的情况下使用。
如果传递了第二个参数,而且该参数是已有窗口或框架的名称,那么就会在具有该名称的窗口或框架中加载第一个参数指定的 URL。
//等同于<a href="http://www.wrox.com" target="topFrame"></a>
window.open("http://www.wrox.com/", "topFrame");
如果名叫 "topFrame" 的窗口或者框架,就会在该窗口或框架加载这个 URL;否则,就会创建一个新窗口并将其命名为 "topFrame"。此外,第二个参数也可以是下列任何一个特殊的窗口名称: _self、_parent、_top 或 _blank。
- 弹出窗口
如果第二个参数并不是已存在的窗口或框架,那么该方法就会根据在第三个参数位置上传入的字符串创建一个新窗口或新标签页。如果没有传入第三个参数,那么就会打开一个带有全部默认设置的新浏览器窗口。在不打开新窗口的情况下,会忽略第三个参数。
第三个参数是一个逗号分隔的设置字符串,表示在新窗口中都显示那些特性。
window.open("http://www.wrox.com/","wroxWindow", "height=400,width=400,top=0,left=10,resizable=yes");
window.open()
方法会返回一个指向新窗口的引用。引用的对象与其他window
对象大致相似,但可以对其进行更多控制。
var wroxWin = window.open("http://wrox.com/","wroxWindow");
wroxWin.resizeTo(500,500);
wroxWin.moveTo(100,100);
wroxWin.close();
- 安全机制
- 弹出窗口屏蔽程序
var wrox = window.open("http://www.wrox.com", "_blank");
if(wroxWin == null) {
alert("The popup was blocked!");
}
如果是浏览器扩展或其他程序阻止的弹出窗口,那么window.open()
通常会抛出一个错误。
var blocked = false;
try {
var wrox = window.open("http://www.wrox.com", "_blank");
if (wroxWin == null) {
blocked = true;
}
}catch (ex) {
blocked = true;
}
if (blocked) {
alert("The popup was blocked!");
}
8.1.6 间歇调用和超时调用
超时调用需要使用window
对象的setTimeout()
方法,它接受两个参数:要执行的代码和以毫秒表示的时间(即在执行代码前需要等待多少毫秒)。其中,第一个参数可以是一个包含 JavaScript 代码的字符串,也可以是一个函数。
//不推荐传递字符串
setTimeout("alert("Hello world!")", 1000);
//推荐的调用方式
setTimeout(function(){alert("hello world!")}, 1000);
第二个参数告诉 JavaScript 再过多长时间把当前任务添加到队列中。如果队列是空的,那么添加的代码会立即执行,否则,得等前面的代码执行完毕之后在执行。
调用 setTimeout()
之后,该方法会返回一个数值 ID,表示超时调用。这个超时调用 ID 是计划执行代码的唯一标识符,可以通过它来取消超时调用。
var timeoutId = setTimeout(function () {alert("hello world!");}, 1000);
//
clearTimeout(timeoutId);
间歇调用与超时调用类似,只不过它会按照指定的时间间隔重复执行代码,直至间歇调用被取消或者页面被卸载。
setInterval(function(){alert("hello world!");}, 1000);
var intervalId = ...
clearInterval(intervalId);
使用超时调用来模拟间歇调用是一种最佳模式,因为后一个间歇调用可能会在前一个间歇调用结束之前启动。所以,最好不要使用间歇调用。
8.1.7 系统对话框
浏览器通过 alert()
、confirm()
和prompt()
方法可以调用系统对话框向用户显示消息。系统对话框与在浏览器中显示的网页没有关系,也不包含 HTML。它们的外观由操作系统及(或)浏览器设置决定,而不是由 CSS 决定。此外,通过这几个方法打开的对话框都是同步和模态的。也就是说,显示这些对话框的时候代码会停止执行,而关掉这些对话框后代码又会恢复执行。
为了确认用户是单击了 OK 还是 Cancel,可以检查confirm()
方法返回的布尔值。
if (confirm("are you okay?")) {
alert("haha!");
} else {
alert("eee!");
}
prompt()
方法生成的是一个“提示”框,用于提示用户输入一些文本。该方法接受两个参数:要显示给用户的文本提示和文本输入域的默认值(可以是一个空字符串)。
如果用户单击了 OK 按钮,则prompt()
返回文本输入框的值;如果不是则返回null
。
8.2 location 对象
location
对象既是window
对象的属性,也是document
对象的属性;换句话说,window.location
和document.location
引用的是同一个对象。
8.2.1 查询字符串参数
可以像下面这样创建一个函数,用以解析查询字符串,然后返回包含所有参数的一个对象:
function getQueryStringArgs () {
//取得查询字符串并去掉开头的问号
var qs = (location.search.length > 0 ? location.search.substring(1) : "");
//保存数据的对象
var args = {};
//取得每一项
var items = qs.lenth ? qs.split("&") : [];
var item = null;
var name = null;
var value = null;
var i = 0;
var len = items.length;
for (i = 0; i < len; i++) {
item = items[i].split("=");
name = decodeURIComponent(item[0]);
value = decodeURIComponent(item[1]);
if (name.length) {
args[name] = value;
}
}
return args;
}
8.2.2 位置操作
location.assign("http://www.wrox.com");
location.href = "http://www.wrox.com";
...
使用replace()
方法后,用户不能回到前一个页面。
location.reload(); //重新加载(有可能从缓存中加载)
location.reload(true); //重新加载(从服务器中加载)
最好将reload
放在代码的最后一行。
8.3 navigator 对象
现已成为识别客户端浏览器的事实标准。
8.3.1 检测插件
对于非 IE 浏览器,可以使用plugins
数组来达到这个目的。该数组中的每一项都包含下列属性。
- name: 插件的名字。
- description: 插件的描述。
- filename: 插件的文件名。
- length: 插件所处理的 MIME 类型数量。
检测 IE 中的插件比较麻烦。在 IE 中检测插件的唯一方式就是使用专有的ActiveXObject
类型,并尝试创建一个特定插件的实例。要想检查特定的插件,就必须知道其 COM 标识符。
function hasIEPlugin (name) {
try {
new ActiveXObject(name);
return true;
} catch (ex) {
return false;
}
}
//检测 Flash
alert(hasIEPlugin("ShockwaveFlash.ShockwaveFlash"));
//检测 QuickTime
alert(hasIEPlugin("QuickTime.QuickTime"));
//检测所有浏览器中的 QuickTime
function hasQuickTime() {
var result = hasPlugin("QuickTime");
if(!result) {
result = hasIEPlugin("ShockwaveFlash.ShockwaveFlash");
}
}
8.3.2 注册处理程序
8.4 screen 对象
8.5 history 对象
history
是window
对象的属性,因此每个浏览器窗口、每个标签页乃至每个框架,都有自己的history
对象与特定的window
对象关联。
使用go()
方法可以在用户的历史纪录中任意跳转,可以向后也可以向前。该方法接受一个参数,表示向后或向前跳转的页面数的一个整数值。负数表示向后跳转,正数相反。
//后退一页
history.go(-1);
//前进一页
history.go(1);
//前进两页
history.go(2);
也可以给go()
方法传递一个字符串参数,此时浏览器会跳转到历史纪录中包含该字符串的第一个位置---可能后退,也可能前进。如果历史纪录中不包含该字符串,那么这个方法什么也不做。
//跳转到最近的 wrox.com 页面
history.go("wrox.com");
//跳转到最近的 nczonline.net 页面
history.go("nczonline.net");
还可以使用back()
和forward()
来代替go()
。
//后退一页
history.back();
//前进一页
history.forward();
还有一个length
属性,保存着历史纪录的数量。
if (history.length == 0) {
//这应该是用户打开窗口的第一个页面
}
8.6 小结
浏览器对象模型以window
对象为依托,表示浏览器窗口以及页面可见区域。同时,window
对象还是 ECMAScript 中的Global
对象,因而所有全局变量和函数都是它的属性,且所有原生的构造函数及其他函数也都存在与它的命名空间下。
- 在使用框架时,每个框架都有自己的
window
对象以及所有原生构造函数及其他函数的副本。每个框架都保存在frames
集合中,可以通过位置或通过名称来访问。 - 有一些窗口指针,可以用来引用其他框架,包括父框架。
-
top
对象始终指向最外围的框架,也就是整个浏览器窗口。 -
parent
对象表示包含当前框架的框架,而self
对象则回指window
。 - 使用
location
对象可以通过编程方式来访问浏览器的导航系统。设置相应的属性,可以逐段或整体性地修改浏览器的 URL。 - 调用
replace()
方法可以导航到一个新 URL,同时 URL 会替换浏览器历史纪录中当前显示的页面。 -
navigator
对象提供了与浏览器有关的信息。到底提供哪些信息,很大程度上取决于用户的浏览器;不过,也有一些公共的属性存在于所有浏览器中。